ITPub博客

首页 > > > Linux命令学习手册-awk

Linux命令学习手册-awk

作者:vaqeteart 时间:2020-03-12 18:03:43 0 删除 编辑



`awk '条件类型1{动作1} 条件类型2{动作2} ...' filename`

# 功能

相较于 `sed` 常常作用于一整个行的处理, `awk` 则比较倾向于一行当中分成数个『字段』来处理。

# 描述

## awk 的处理流程

1. 读入第一行,并将第一行的资料填入 $0, $1, $2…. 等变数当中;

2. 依据 "条件类型" 的限制,判断是否需要进行后面的 "动作";

3. 做完所有的动作与条件类型;

4. 若还有后续的『行』的数据,则重复上面 1~3 的步骤,直到所有的数据都读完为止。

经过这样的步骤,您会晓得, awk 是『以行为一次处理的单位』, 而『以字段为最小的处理单位』。

## 常用变量(变量名称 代表意义)

`NF` 每一行 ( `$0` ) 拥有的字段总数

`NR` 目前 awk 所处理的是『第几行』数据

`FS` 目前的分隔字符,预设是空格键

每一行的每个字段的变量名称就是 `$1`, `$2` … 等。还有个例外,那就是 `$0` 代表一整行的意思。

注意, `awk` 后续的所有动作以 ' 括住, 所以,内容如果想要以 `print` 打印时,记得,非变量的文字部分, `printf` 提到的格式中,都需要使用双引号.

## 逻辑运算符号

> 大于

< 小于

>= 大于或等于

<= 小于或等于

== 等于

!= 不等于

# 举例

## 假设输入输出如下:

$last

dmtsai pts/0 192.168.1.12 Mon Aug 22 09:40 still logged in

root tty1 Mon Aug 15 11:38 - 11:39 (00:01)

reboot system boot 2.6.11 Sun Aug 14 18:18 (7+15:41)

dmtsai pts/0 192.168.1.12 Fri Aug 12 12:07 - 12:08 (00:01)

- 打印每行的第1列和第三列,并且用[TAB]隔开

输入输出如下

$last | awk '{print $1 "\t" $3}'

dmtsai 192.168.1.12

root Mon

reboot boot

dmtsai 192.168.1.12

这里,我们没有设定条件,也就是无论哪一行都做同样处理,所以第2,3行显示的有点"不正常"。由此可知awk是“迭代”处理每一行的。

- 列出每一行的账号,目前处理的行数, 以及该行有多少字段

输入输出如下

$last | awk '{print $1 "\t lines: " NR "\t columes: " NF}'

dmtsai lines: 1 columes: 10

root lines: 2 columes: 9

reboot lines: 3 columes: 9

dmtsai lines: 4 columes: 10

- 查阅 `/etc/passwd` ,第3栏小于 10 以下的数据,并且仅列出账号与第3栏

输入输出如下:

$cat /etc/passwd | awk '{FS=":"} $3 < 10 {print $1 "\t " $3}'

root:x:0:0:root:/root:/bin/bash

bin 1

daemon 2

......(以下省略)......

这里,在 `/etc/passwd` 当中是以冒号 ":" 来作为字段的分隔,所以需要设置一下。但是我们读入第一行的时候, 那些变数 $1, $2… 预设还以空格键为分隔,所以虽然我们定义了 FS=":" 了, 但是却仅能在第二行后才开始生效(可能因为一般第一行仅仅是列名不需处理,而这里却是特例,见例4改进)。

- 对上面过滤的操作改进

输入输出如下:

$ cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t " $3}'

root 0

bin 1

daemon 2

......(以下省略)......

利用 BEGIN 这个关键词,可以从第一行就生效了。实际除了BEGIN,还有END。

## 假设如下表(pay.txt)

Name 1st 2nd 3th

VBird 23000 24000 25000

DMTsai 21000 20000 23000

Bird2 43000 42000 41000

- 计算每一行总额,添加追加到最后一列

输入输出如下:

$awk 'NR==1{printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total" }

NR>=2{total = $2 + $3 + $4

printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'

Name 1st 2nd 3th Total

VBird 23000 24000 25000 72000.00

DMTsai 21000 20000 23000 64000.00

Bird2 43000 42000 41000 126000.00

注意:所有的动作在 `{}` 内,如需多个指令辅助,可利用分号 `;` 间隔或直接以 `[Enter]` 按键来隔开每个指令,例如上面的 NR>=2 后面接的动作, 利用 total = … 那个指令来指定加总,而后续则以 `printf` 来格式化输;格式化输出时,在 `printf` 的格式设定当中,务必加上 `\n` ,才能进行分行;与 `bash shell` 的变量不同,在 `awk` 当中,变量可以直接使用,不需加上 `$` 符号(如total)。

# 其它

参考资料: [《鸟哥的私房菜》](http://linux-vbird.bluedata.org/linux_base/0330regularex.htm#basic_regexp_char)

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9525959/viewspace-3135100/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
软件开发者,擅长嵌入式Linux软件开发、Linux系统操作、时间管理、其它。

注册时间:2009-03-17

  • 博文量
    60
  • 访问量
    12563