详解著名的awk Oneliner,第三部分:选择性输出特定行
输出文件的前10行(模拟 head -n 10 )
awk ‘ NR < 11 ‘
如前所述,这里省略了动作,即为打印输出。匹配模式是变量NR需要小于11,NR即为当前的行号。这个写法很简单,但是有一个问题,在NR大于10的时候,awk其实还是对每行进行了判断,如果文件很大,比如说有上万行,浪费的时间是无法忽略的。所以,更好的写法是
awk ‘1; NR = 10 { exit }‘
第一句对当前行进行输出。第二句判断是不是已经到了第10行,如果是则退出。
输出文件的第一行(模拟 head -n 1 )
awk ‘NR > 1 { exit }; 1‘
这个例子与前一个很相似,中心思想就是第二行就退出。
输出文件的最后两行(模拟 tail -n 2 )
awk ‘{ y=x "\n" $0; x=$0}; END { print y }‘
的确,这一句看起来确实有些别扭。第一句总是把一个在当前行前面再加上变量x的内容赋值给y,然后用x记录当前行内容。这样的效果是y的内容始终是上一行加上当前行的内容。在最后,输出y的内容。如果仔细看的话,不难发现这个写法是很不高效的,因为它不停的进行赋值和字符串连接,只为了找到最后一行!所以,如果你想要输出文件的最后两行,tail -n 2
是最好的选择。
输出文件的最后一行(模拟 tail -n 1 )
awk ‘END { print }‘
句法方面没什么好说的,print省略参数即是等价于print $0
。但是这个语句可能不能被非GNU awk的某些awk版本正常执行,如果为了兼容,下面的写法是最安全的:
awk ‘{ rec = $0 }; END { print rec }‘
输出只匹配某些模式的行(模拟 grep )
awk ‘/regex/‘
似乎没什么好说的了。
输出不匹配某些模式的行(模拟 grep -v )
awk ‘!/regex/‘
匹配模式前加“!”就是否定判断结果。
输出匹配模式的行的上一行,而非当前行
awk ‘/regex/ { print x }; { x = $0 }‘
变量x总是用来记录上一行的内容,如果模式匹配了当前行,则输出x的内容。
输出匹配模式的下一行
awk ‘/regex/ { getline; print }‘
这里使用了getline函数取得下一行的内容并输出。getline的作用是将$0的内容置为下一行的内容,并同时更新NR,NF,FNR变量。如果匹配的是最后一行,getline会出错,$0不会被更新,最后一行会被打印。
输出匹配AA或者BB或者CC的行
awk ‘/AA|BB|CC/‘
没什么好说的,正则表达式。如果有看不懂的朋友,请自行学习正则表达式。
输出长过65个字符的行
awk ‘length > 64‘
length([str])
返回字符串的长度,如果参数省略,即是以$0作为参数,括号也可以省略了。
输出短于65个字符的行
awk ‘length < 65‘
和上例基本一样。
输出从匹配行到最后一样的内容
awk ‘/regex/,0‘
这里使用了“pattern1,pattern2”的形式来指定一个匹配的范围,其中pattern2这里为0,也就是false,所以一直会匹配到文件结束。
从第8行输出到第12行
awk ‘NR==8,NR==12‘
同上例,这也是个范围匹配。
输出第52行
awk ‘NR==52‘
如果想要少执行些不必要的循环,就这样写:
awk ‘NR==52 {print;exit}‘
输出两次正则表达式匹配之间的行
awk ‘/regex1/, /regex2/‘
删除所有的空行
awk NF
NF为真即是非空行。另外一种写法是用正则表达式:
awk ‘/./‘
这个很类似grep .
的思路,但是是不如awk NF
好的,因为“.”也是可以匹配空格和TAB的。