13

Awk这件上古神兵你会用了吗

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzUzMzE4MDY0Nw%3D%3D&%3Bmid=2247483893&%3Bidx=1&%3Bsn=85f6a2063048cc244aedde3172444e32
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

花括号MC(huakuohao-mc):关注JAVA基础编程及大数据,注重经验分享及个人成长。

AWK 诞生于1977的贝尔实验室,是由 Alfred Aho,Peter Weinberger和Brian Kernighan三位大神开发, AWK 的命名是由三位作者的Family Name的首字母组成。

三位大神开发 AWK 的初衷是为了方便快速的处理文本及数据信息,在当年那个即没有 python 也没有 go 的年代,这是一个很酷也很有意义的事情;不过话说回来,即便是现在有了 Python Go AWK 在日常线上运维方面仍然占据一席之地,而且几乎不可替代。

如果你对 AWK 还是不甚了解,那么希望通过这篇博文,能够让各位做个简单入门,如果这篇文章还能提起你学习 AWK 的兴趣就更好了。

AWK 的程序一般都很短,但并不是说 AWK 写不出逻辑复杂的程序。 AWK 像你学过的其它语言一样,支持变量自定义,数组结构, for 循环等等,同时也支持自定义函数。

假设我们打算处理一个在线商店的后台日志,内容如下:

1python基础教程 山治 34.50 5
2python高级教程 索隆 40.00 6
3python实战 娜美 38 3
4java编程思想 弗兰克 48.00 6
5Vue教程 javascript小组 55.00 8
6awk基础教程 路飞 42 3

第一列为书名,第二列为作者,第三列为价格,第四列为当日销售数量。我们将该文件命名为 awk_books.log 。接下来我们将通过一些实际的案例需求来学习 AWK

找出价格大于40的书籍

1awk '$3>40 {print $0}' awk_books.log

输出:

1$ awk '$3>40 {print $0}' awk_books.log
2java编程思想 弗兰克 48.00 6
3Vue教程 javascript小组 55.00 8
4awk基础教程 路飞 42 3

解释

awk 的意思是告诉操作系统我要执行 awk 程序,请做好准备。单引号里面的内容为具体的程序逻辑。 awk_books.log 为要处理的文件。

awk 的程序其实很简单,因为是有固定套路的。套路就是 'pattern {action}' , pattern 称为模式, action 称为动作。

awk 会自动读入要处理文件的每一行内容,依次用 pattern 去匹配,如果匹配成功,则执行 action 。对于上面的例子, pattern $3>40 , action {print $0}

注意: pattern action 不必同时存在,后面我会有例子给大家解释什么意思。

到此为止,对于上面的小例子,除了 $3 $0 你还不理解以外,其它应该都了解了。

awk 会将输入的每一行按照空白字符进行分隔,因此分隔之后的第一列就是 $1 ,第二列就是 $2 ,以此类推,我们的例子中书价在第三列,自然就是 $3 ,变量 $0 则代表整行记录。

如果要处理的文本内容不是按照空白字符分隔怎么办?你可以这样处理。

1echo "hello-world" | awk 'BEGIN{FS="-"} {print $1}'

输出的结果都为 hello

FS awk 的内置变量,表示输入列的分隔符,默认为空白符。上面的例子中我们将 FS 的默认值设置成我们希望的样子,也就是 - 。除了 FS 以外,跟分隔符相关的内置变量还有输出列分隔符 OFS ,输入行分隔符 RS ,输出行分隔符 ORS 。我就不一一举例展示了。

BEGIN 表示的意思是 AWK 程序开始执行之前,执行 BEGIN 关键字之后的语句,而且只执行一次,所以经常用来初始化变量或者文件头。除了 BEGIN ,还有 END ,我后面还会有例子介绍,大家不要着急。

好了,这里先做个简单的小结,然后继续出发。

1.我们知道了如何在命令行终端调用

AWK

程序。

2.知道了

AWK 程序的固定套路为 'pattern {action}'

格式

3.了解了内置变量

$0 , $1 ,以及 FS 的作用。

接下来通过一些具体的样例继续学习。

打印出每一行最后一列

1awk '{print $NF}' awk_books.log

输出结果:

1$ awk '{print $NF}' awk_books.log
25
36
43
56
68
73

这个例子中,明显没有 pattern 而只有 action AWK 中如果没有 pattern ,则默认匹配所有行。而 NF AWK 的内置变量,表示每一行有多少列。所以 $NF 自然就代表着最后一列的输出内容。基于这个例子,你可以尝试着打印出每一行的倒数第二列内容,代码如下:

1awk '{print $(NF-1) }' awk_books.log

只打印出第二行内容

1awk 'NR == 2' awk_books.log

输出结果:

1$ awk 'NR == 2' awk_books.log
2python高级教程 索隆 40.00 6

这个例子明显没有 action 只有 pattern ,如果没有写 action 则执行默认 action ,默认的 action 就是打印匹配的行内容。 NR 也是内置变量,表示 AWK 已经读取的行数。

打印每一行的内容及行号

1awk '{print NR,$0}' awk_books.log

输出结果:

1$ awk '{print NR,$0}' awk_books.log
21 python基础教程 山治 34.50 5
32 python高级教程 索隆 40.00 6
43 python实战 娜美 38 3
54 java编程思想 弗兰克 48.00 6
65 Vue教程 javascript小组 55.00 8
76 awk基础教程 路飞 42 3

print 里面用逗号分隔要打印的多个内容,输出的时候逗号会被空格替代。

更好的输出
接上面的例子,我们让输出结果更易读一些。

1awk 'BEGIN{print"编号    书名    作者 价格 销量"; print""} {print NR,$0} END{print"";print "输出结束!"}' awk_books.log

输出结果

 1$ awk 'BEGIN{print"编号    书名    作者 价格 销量"; print""} {print NR,$0} END{print"";print "输出结束!"}' awk_books.log
 2编号    书名    作者 价格 销量
 3
 41 python基础教程 山治 34.50 5
 52 python高级教程 索隆 40.00 6
 63 python实战 娜美 38 3
 74 java编程思想 弗兰克 48.00 6
 85 Vue教程 javascript小组 55.00 8
 96 awk基础教程 路飞 42 3
10
11输出结束!

BEGIN ,在前面已经提到了过了,这里是为了加深一下大家的理解。 BEGIN END 后面跟随的语句都只执行一次,即在程序的开头和结束。

打印包含Java的行

1awk '/java/ {print $0}' awk_books.log

输出结果:

1$ awk '/java/ {print $0}' awk_books.log
2java编程思想 弗兰克 48.00 6
3Vue教程 javascript小组 55.00 8

这个样例的匹配模式是个正则表达式,只要有匹配的内容就会输出对应的行。你可以根据业务需求写出更复杂的正则表达式。

打印第一列包含java的行

1awk '$1 ~/java/ {print $0}' awk_books.log

输出结果:

1$ awk '$1 ~/java/ {print $0}' awk_books.log
2java编程思想 弗兰克 48.00 6

打印第一列不包含Java的行

1awk '$1 !~/java/ {print $0}' awk_books.log

输出结果:

1$ awk '$1 !~/java/ {print $0}' awk_books.log
2python基础教程 山治 34.50 5
3python高级教程 索隆 40.00 6
4python实战 娜美 38 3
5Vue教程 javascript小组 55.00 8
6awk基础教程 路飞 42 3

统计输入文本的总行数

1awk 'END {print NR}' awk_books.log

输出结果:

1$ awk 'END {print NR}' awk_books.log
26

输出字符数超过33的行

1awk 'length($0)> 33' awk_books.log

输出结果:

1$ awk 'length($0)> 33' awk_books.log
2java编程思想 弗兰克 48.00 6
3Vue教程 javascript小组 55.00 8

length 为内置函数,此外还有很多内置函数,不在此一一列举了,感兴趣的可以去查。

输出价格最高的行

1awk '$3>max {max = $3; maxline=$0} END {print max,maxline}' awk_books.log

输出结果:

1$ awk '$3>max {max = $3; maxline=$0} END {print max,maxline}' awk_books.log
255.00 Vue教程 javascript小组 55.00 8

这里 max maxline 为自定义变量, AWK 里面的变量不用事先声明,直接用就OK,默认值为空或者0。

计算当天销售总价并输出

1awk '{total += $3*$4} END { print total}' awk_books.log

输出结果:

1$ awk '{total += $3*$4} END { print total}' awk_books.log
21380.5

找出所有Python的书目,然后按照价格排序

1awk '$1 ~/python/ {print $0}' awk_books.log|sort -n -k 3 -t ' '

输出结果:

1$ awk '$1 ~/python/ {print $0}' awk_books.log|sort -n -k 3 -t ' '
2python基础教程 山治 34.50 5
3python实战 娜美 38 3
4python高级教程 索隆 40.00 6

找出所有Python的书目,按照价格排序,并输出价格最高的两条

1awk '$1 ~/python/ {print $0}' awk_books.log|sort -r -n -k 3 -t ' '|head -n 2

输出结果:

1$ awk '$1 ~/python/ {print $0}' awk_books.log|sort -r -n -k 3 -t ' '|head -n 2
2python高级教程 索隆 40.00 6
3python实战 娜美 38 3

最后两个列子借助了 sort head ,不了解两个指令的可以去查一下,这里不做过多的介绍了。

好了,以上这些 AWK 知识应该够各位应付日常的工作需求了。如果还不够怎么办呢?去买两本书,继续深入学啊!

·END·

花括号MC

Java·大数据·个人成长

rAryeqV.jpg!web

微信号:huakuohao-mc

点一下你会更好看耶

7J7VZvy.gif


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK