awk命令详解(一)

一、awk内置变量

名称

含义
ARGC命令行参数个数
ARGV命令行参数排列
ENVIRON支持队列中系统环境变量的使用
FILENAMEawk浏览的文件名
FNR浏览文件的记录数
FS设置输入域分隔符,等价于命令行-F选项
NF浏览记录的域的个数
NR已读的记录个数
OFS输出域分隔符
ORS输出记录分隔符
RS控制记录分隔符

1.1ARGV和ARGC举例:

ARGV表示awk命令的参数,需要注意的是awk命令本身也是一个参数,在下面的命令中,参数有四个,分别是:awk、1、2、3,因此ARGC=4。
[root@randow_wz mnt]# awk 'BEGIN{for(i=0; i<ARGC; i++) print ARGV[i]}' 1 2 3
awk
1
2
3

1.2ENVIRON举例

ENVIRON是一个数组,下标为对应环境变量的值,元素为对应的环境变量。下例中,使用OFS指定输出域的分隔符为冒号,方便查看。

[root@random_wz mnt]# awk 'BEGIN{OFS=":"; for(x in ENVIRON) print x,ENVIRON[x]}'
AWKPATH:.:/usr/share/awk
HOME:/root
PWD:/mnt

1.3 FNR和NR举例

NR表示已读的记录数,FNR表示浏览文件的记录数,小于等于NR(比如当读取第二个文件时,FNR是从1开始重新计数,而NR不会)。NR==FNR:用于在读取两个或两个以上的文件时,判断是不是在读取第一个文件。

对于NR,读取不同文件,NR是一直++的,但是FNR当读取新文件时,值是从1开始的。
[root@random_wz mnt]# cat 1.txt
aaa
bbb
ccc
[root@random_wz mnt]# cat 2.txt
ddd
eee
fff
[root@random_wz mnt]# awk '{OFS=":";print FNR,$0}' 1.txt 2.txt
1:aaa
2:bbb
3:ccc
1:ddd
2:eee
3:fff
[root@random_wz mnt]# awk '{OFS=":";print NR,$0}' 1.txt 2.txt
1:aaa
2:bbb
3:ccc
4:ddd
5:eee
6:fff

1.4 FILENAME举例

FILENAME表示输入的文件名称

[root@random_wz mnt]# awk 'END{print FILENAME}' 1.txt
1.txt

1.5 RS和ORS举例

ORS表示输出记录分隔符,比如分隔符默认为换行符,你可以指定在输出的时候用其他分割符表示,RS表示控制记录分隔符,即你可以指定分隔符。

默认以换行符分割域,使用ORS指定输出时将换行符用*替换
[root@random_wz mnt]# cat 1.txt
aaa
bbb
ccc
[root@random_wz mnt]# awk 'BEGIN{ORS="*"}{print $0}' 1.txt
aaa*bbb*ccc*
通过RS指定每条记录的分割符为|
[root@random_wz mnt]# cat 1.txt
aaa|bbb|ccc
[root@random_wz mnt]# awk 'BEGIN{RS="|"}{print $0}' 1.txt
aaa
bbb
ccc

1.6 NF和NR举例

NF表示浏览记录域的个数,NR为已读的记录个数。

$NF表示最后一个域
[root@random_wz mnt]# cat 1.txt
aaa
bbb
ccc
[root@random_wz mnt]# awk 'BEGIN{OFS=":"}{print NR,$NF}' 1.txt
1:aaa
2:bbb
3:ccc

二、流程控制

2.1 条件判断语句(if)

格式为:if(表达式)  语句一  else 语句二

当然你也可以将多个语句用{}括起来,Unix awk命令允许嵌套,如下:

if(表达式)  {语句一}  else if(表达式二) 语句二 else  {语句三}

举两个例子,第一个不嵌套:


[root@random_wz mnt]# awk 'BEGIN{test=20; if(test>10) print "very good"; else print "bad"}'
very good
注意上面的例子中,如果命令写在一行,则需要注意加分号,其中if(表达式) 语句一为一个整体,在语句一后面加分号,else语句二为一个整体,如果else语句在最后,则可以不加分号,在下面的例子中展示了分行时可以省略分号的例子。
[root@random_wz mnt]# awk 'BEGIN{
> test=20
> if(test>10)
> print "very good"
> else
> print "bad"
> }'
very good

第二个例子,使用{}将语句括起来

[root@random_wz mnt]# awk 'BEGIN{
> test=70
> if(test=70)
> {
>     print "***********************************************"
>     print "   Wishing China 70 Years Old Happy birthday   "
>     print "***********************************************"
> }
> else if(test>100)
{
>     print "Good"
> }
> else
> {
>     print "Bad"
> }
> }'
***********************************************
   Wishing China 70 Years Old Happy birthday
***********************************************
如果写在一行,注意要加分号。

2.2 while语句

格式:while(表达式) {语句}

直接上个例子

[root@random_wz mnt]# awk 'BEGIN{
> Sum=0
> i=0
> while(i<5)
> {
>     print Sum,"+",i,"=",Sum+i
>     Sum+=i
>     i++
> }
> }'
0 + 0 = 0
0 + 1 = 1
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10

我在学习while的时候发现一个问题,当awk语句后面没有文件的时候,只有BEGIN语句可以执行,来一个例子说明:

[root@random_wz mnt]# awk 'BEGIN{
> Sum=0
> i=0
> while(i<5)
> {
>     print Sum,"+",i,"=",Sum+i
>     Sum+=i
>     i++
> }
> }
> END{
>     print "Sum=",Sum
> }'
0 + 0 = 0
0 + 1 = 1
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
执行后鼠标会一致卡在这

鼠标一直卡着的原因如下:

  • BEGIN{},为行前处理,也就是在行之前操作,通常为初始化操作,是可选项,当awk语句只有BEGIN时,不需要再后面接文件。
  • {},awk语法的第二部分为行处理,用来处理读入的行,因此当awk语句中有行处理部分的话必须要再后面接需要进行处理的文件名称。
  • END{},为行后处理,awk命令将所有的行处理完成后执行的操作,一般输出处理结果,因此当awk语句中包含END语句的时候,后面必须要接需要处理的文件名称,这也是为什么上面的例子会一直卡住的原因。

2.3 do-while循环

格式:do {语句} while(条件)

格式和C语言中的do-while是一致的,举例如下:

[root@random_wz mnt]# awk 'BEGIN{
> Sum=0
> i=0
> do
> {
>     print Sum,"+",i,"=",Sum+i
>     Sum+=i
>     i++
> }
> while(i<10)
> }'
0 + 0 = 0
0 + 1 = 1
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
10 + 5 = 15
15 + 6 = 21
21 + 7 = 28
28 + 8 = 36
36 + 9 = 45

2.4 下面介绍流程控制语句中会用到的一些语句

语句含义
break当 break 语句用于 while 或 for 语句时,导致退出程序循环。
continue当 continue 语句用于 while 或 for 语句时,使程序循环移动到下一个迭代。
next能够导致读入下一个输入行,并返回到脚本的顶部。这可以避免对当前输入行执行其他的操作过程。
exit语句使主输入循环退出并将控制转移到END,如果END存在的话。如果没有定义END规则,或在END中应用exit语句,则终止脚本的执行。

 

 

 

 

 

 

 

 

这里举个例子说一下next的用法:

[root@viper-unity-va-ut-ff2103-24 mnt]# cat 1.txt
No      Item_Name               Price           Quantity
1       Mangoes                 $3.45              5
2       Apples                  $2.45              25
3       Pineapples              $4.45              55
4       Tomatoes                $3.45              25
5       Onions                  $1.45              15
6       Bananas                 $3.45              30
[root@viper-unity-va-ut-ff2103-24 mnt]# awk '$4 <= 20 { printf "%s\t%s\n", $0,"*" ; } $4 > 20 { print $0 ;} ' 1.txt
No      Item_Name               Price           Quantity
1       Mangoes                 $3.45              5    *
2       Apples                  $2.45              25
3       Pineapples              $4.45              55
4       Tomatoes                $3.45              25
5       Onions                  $1.45              15   *
6       Bananas                 $3.45              30

上面的例子是给价格不超过20的水果条目后面加一个星号,每次第一个判断完成后,还会进行第二次判断,会比较良妃时间,因此加入next语句,在第一次判断完后,满足条件,会跳过第二个判断,从而开始新的迭代。

[root@viper-unity-va-ut-ff2103-24 mnt]# awk '$4 <= 20 { printf "%s\t%s\n", $0,"*" ; next; } $4 > 20 { print $0 ;} ' 1.txt
No      Item_Name               Price           Quantity
1       Mangoes                 $3.45              5    *
2       Apples                  $2.45              25
3       Pineapples              $4.45              55
4       Tomatoes                $3.45              25
5       Onions                  $1.45              15   *
6       Bananas                 $3.45              30

三、printf语句

最后简单说一下printf语句在awk命令中的使用,前面的例子已经出现过,在awk语句中printf的用法和在C语言中是一致的。

这里通过表格列出来一些常用的修饰符。

修饰符含义
-左对齐修饰符
#

显示8进制整数前面加个0

显示16进制整数前面加0x

+整数前面加正负号
0用0填充所显示的值

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值