awk和sed结合起来,对于文件的横向纵向处理几乎是全方位的,可以算是文本处理中的大招了。当然awk这一强大的分本处理工具也不是浪得虚名,功能丰富,学习周期也要长些,不是一个Help文档就能说完的。学习awk可以算得上重新学习一门编程语言,因为里面的东西确实太多了。我们就按部就班,循序渐进,先来说说awk中的变量。
关于awk中的变量,有内置变量和自定义变量。
内置变量如果细分,有数据字段和数据行变量,数据变量,可能看概念不好理解。我们一个一个说明。
数据字段和数据行变量主要有
FIELDWIDTHS 会根据字段的长度来划分,比如20150401.223300 如果我们指定FIELDWIDTHS为3 5 3 4 则输出为201 50401 .22 3300
FS 这个是输入字段的分隔符,比如 11,12,13 如果指定FS为, 就会把11,12,13分隔为 11 12 13
OFS 这个是输出字段的分隔符,比如 11,12,13 如果我们按照,分隔,数据会为11 12 13,我们指定OFS为“--”,则输出为11--12--13
RS 这个是输入数据行的分隔符,使用的场景较为特殊,在下面通过例子来说明。
ORS 这个是输出数据行的分隔符,使用的场景较为特殊,通过例子来说明。
我们指定一个文件 a.lst,还是举个pm2.5的例子。以下是近些天的pm2.5的数据
2015 03 30 100
2015 03 31 150
2015 04 01 70
? awk 'BEGIN{FS=" "}{print $1 $2 $3}' a.lst
20150330
20150331
20150401
注意下面两种写法的差别。
? awk 'BEGIN{FS=" " ;OFS="--"}{print $1 $2 $3}' a.lst
20150330
20150331
20150401
? awk 'BEGIN{FS=" " ;OFS="--"}{print $1,$2,$3}' a.lst
2015--03--30
2015--03--31
2015--04--01
关于RS和ORS的使用可以使用下面的例子。
假设我们存在下面的文件,每隔3行数据就来一个空行。我们可以选择性的截取数据字段的值
? cat a.lst
2015line1 03 30 100
2015 03 31 150
2015 04 01 70
2015line2 03 30 100
2015 03 31 150
2015 04 01 70
2015line3 03 30 100
2015 03 31 150
2015 04 01 70
? awk 'BEGIN{FS="\n"; RS=""}{print $1,$3}' a.lst --这个地方,我们使用RS来分隔数据行,以空行为分界,在这个基础上按照回车划分每一列数据。
2015line1 03 30 100 2015 04 01 70
2015line2 03 30 100 2015 04 01 70
2015line3 03 30 100 2015 04 01 70
这样就把第1行,第3行的数据整合到了一起。按照这个规律下面的数据也是这样的形式。
如果使用ORS来,结果会大不相同,我们以“--”作为输出的分隔符。
? awk 'BEGIN{FS="\n"; ORS="----"}{print $1,$3}' a.lst
2015line1 03 30 100 ----2015 03 31 150 ----2015 04 01 70 ---- ----2015line2 03 30 100 ----2015 03 31 150 ----2015 04 01 70 ---- ----2015line3 03 30 100 ----2015 03 31 150 ----2015 04 01 70 ---- ---- ----
对于数据变量,可能使用的地方相对要少一些。内建变量比如:
ARGC 代表当前命令行的参数个数
ARGV 包含命令行参数的数组
ENVIRON 代表当前shell环境变量和值组成的关联数组
NF 代表数据文件中的字段总数
NR 是已处理的输入数据行数目
举几个例子。
? awk 'BEGIN{print ARGC,ARGV[0],ARGV[1]}' a.lst
2 awk a.lst
其中ARGC是命令行的参数个数,可以看到两个参数的值分别为awk和a.lst,下标从0开始
? awk '{print ENVIRON["HOME"] ,ENVIRON["PATH"]}' a
/home/mobaxterm /bin:/bin:/drives/c/WINDOWS:/drives/c/WINDOWS/system32
自定义变量的部分是平时使用频率比较高的,这个部分的灵活性还是很大的。基本上有以下几个场景。
在脚本中给变量赋值,在命令行上给变量赋值
脚本中给变量赋值,比如我们指定一个变量test,然后初始化两次,变量值都会动态变化
? awk '
> BEGIN{
> test="first_try"
> print test
> test="second_try"
> print test
> }'
first_try
second_try
对于命令行中给变量赋值,可以这么理解。
? cat a.lst
2015line1 03 30 100
2015 03 31 150
2015 04 01 70
? awk 'begin{FS=" "}{print $n}' n=3 a.lst
30
31
01
这种情况下,会根据设置的变量值,动态赋予n=3
如果需要传递shell变量的值,可以通过-v选项来实现
? awk -v n=3 '{print "this is a test",n}' a
this is a test 3
test=aaaaa
echo $test
aaaa
? awk -v t=$test '{print "testing value:" t}' a.lst
testing value:aaaa
testing value:aaaa
testing value:aaaa