Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5580236
  • 博文数量: 922
  • 博客积分: 19333
  • 博客等级: 上将
  • 技术积分: 11226
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-27 14:33
文章分类

全部博文(922)

文章存档

2023年(1)

2020年(2)

2019年(1)

2017年(1)

2016年(3)

2015年(10)

2014年(17)

2013年(49)

2012年(291)

2011年(266)

2010年(95)

2009年(54)

2008年(132)

分类: LINUX

2010-08-08 20:03:31

参考资料:《鸟哥的私房菜》


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


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


【举例】

假设输入:

$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:打印每行的第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是“迭代”处理每一行的。


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

$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


例3:查阅/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改进)。


例4:对例3改进:

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

输入之后,输出如下:

root     0

bin      1

daemon   2

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

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


例5:假设如下表(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)。


【描述】

1)awk 的处理流程是:

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

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

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

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

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

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

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

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

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

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

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

3)逻辑运算符号: 

>  大于 

<  小于 

>=  大于或等于 

<= 小于或等于 

==  等于 

!=  不等于 



日期:2009-11-23
阅读(1166) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

vaqeteart2020-01-16 11:42:09

to org