我们知道Linux三剑客,他们是grep、sed、awk。之前已经讲过grep和sed了。没有看过的同学可以点击直接阅读。今天要分享的是比较强大的awk。sed可以实现非交互式的字符串替换,grep可以实现有效的过滤功能。两者相比,awk是一个强大的文本分析工具,尤其是在分析数据和生成报告的时候功能强大。awk的强大功能是一般Linux命令无法比拟的。在本文中,我不会通过告诉您awk也是一种编程语言来吓唬您。我们只要把它想象成Linux下一个强大的文本分析工具就可以了。在这篇文章中,我仍然坚持实用和实践的原则,并提供了大量的例子,但我不会面面俱到。本文可以帮助你快速使用awk,这些东西足以应对工作中的大部分应用场景。在学习场景的具体使用之前,我们先来看看awk可以做什么:1.可以将给定的文本内容按照我们期望的格式输出显示,并打印成报表。2、分析处理系统日志,快速分析挖掘我们关心的数据,生成统计信息;3、方便使用统计数据,如网站访问量、IP访问量等;4、通过多种工具的结合,快速汇总分析系统的运行信息,让您对系统的运行情况了如指掌;5、强大的脚本语言表达能力,支持循环、条件、数组等语法,帮你分析更复杂的数据;……当然,awk不仅仅可以做这些事情,当你整合它的用法时,您可以随心所欲地进行高效的数据分析和统计。但是我们要知道awk并不是万能的,它更擅长处理格式化的文本,比如日志,csv格式的数据等;原理让我们先来简单了解一下awk的基本工作原理,通过下面的图解说明,希望你能了解awk到底是如何工作的。awk的基本命令格式如下图所示,以说明awk的工作原理。首先执行{}中关键字BEGIN标记的命令;完成BEGIN大括号中的命令后,开始执行body命令;逐行读取数据,默认\n拆分后的内容是一条记录,其实就是行的概念;把记录按照指定的分隔符划分成字段,其实就是列的概念;循环执行body块中的命令,每读取一行执行一次body,最后完成body执行;最后,执行END命令,通常在END中输出最终结果;awk是输入驱动的,输入行越多,body命令就会执行多少次。在下面的例子学习中,我们要时刻记住:记录(Record)是行,字段(Field)是列,BEGIN是预处理阶段,body是awk真正工作的阶段,END是最后的处理阶段。实战-入门从以下内容开始,我们直接进入实战。为了示例方便,我先将以下信息保存到file.txt中。我们先拿最简单最常用的awk例子,输出第1、4、8列:大括号内的awk语句只能用单引号括起来包含,其中$1..$N表示的个数columns,$0表示整行内容下面我们来看awk格式化输出的比较实用的功能。和C语言的printf格式输出是一样的。比起C++中的stream方法,我个人更喜欢这种格式化方法。%s表示字符串占位符,-4表示列宽为4,左对齐。我们也可以根据需要列出更复杂的格式,这里不再详细举例。实战-进阶(一)过滤记录有些数据可能不是你想要的,你可以根据自己的需要进行过滤。上面的过滤条件是只输出第三列为root,第六列为10的行。awk支持各种比较运算符!=、>、<、>=、<=,其中$0代表整行的全部内容。(2)内置变量awk有一些内置变量,更方便我们处理数据。以root用户过滤第三列,和第二行的内容,打印时输出行号。NR表示当前行,NF表示当前行的列数。(3)指定分隔符我们的数据并不总是使用空格作为分隔符。我们可以通过FS变量指定分隔符。我们指定分隔符为2019,这样一行的内容就分为两部分,把2019换成*上面的命令也可以通过-F选项指定分隔符,如果需要指定多个分隔符,可以这样做——F'[;:]'。相信只要你聪明,一定能够理解并掌握。同样awk可以在输出的时候指定分隔符。通过OFS变量设置输出时,每个字段由OFS指定的符号分隔。实战-进阶(一)条件匹配列出root用户的所有文件,文件第一行匹配第三列包含root的行,~其实就是正则表达式匹配。还有,awk可以像grep这样匹配一行,另外,/Aug|Dec/可以像这样匹配多个关键字。可以使用模式反转!符号(2)拆分文件我们来做一件有趣的事情,可以将文本信息拆分成多个文件,下面的命令将文件信息按照月份拆分成多个文件(第5列)文件awk支持重定向符号>,直接重定向每行的内容以月份命名的文件。当然你也可以将指定的列输出到文件中。(3)if语句判断复杂的条件,可以使用awk的if语句,awk的强大正是因为它是脚本解释器,具有通用脚本语言的编程能力。以下示例通过稍微复杂的条件拆分文件。请注意,if语句位于大括号内。(4)统计当前目录下,所有*.c和*.h文件占用空间的总和。第五列表示文件大小。每次读取一行时,文件大小将被计算到sum变量中。在最后的END阶段打印出sum,也就是所有文件大小的总和。我们再看一个例子,统计每个用户的进程占用了多少内存。请注意,该值是RSS列。这里使用数组和for循环。值得一提的是,awk的数组可以理解为一个字典或者Map,而key可以是一个数值,也可以是一个字符串,这种数据类型在平时是很常用的。(5)字符串通过下面这个简单的例子,awk支持了一系列的字符串操作。awk支持一系列字符串函数。length计算字符串的长度,toupper函数将字符串转换为大写。实战-技巧为了从整体上理解awk的工作机制,我们来看一个综合性的例子,假设有学生成绩单:因为这个例子程序有点复杂,读起来不太方便命令行。另外,我也想通过这个案例介绍另一种执行awk的方式。我们的awk脚本如下:执行awk的结果如下。我们可以将复杂的awk语句写到脚本文件cal.awk中,然后通过-f选项指定从脚本文件中执行。在BEGIN阶段,我们初始化了相关的变量,打印了header的格式。在body阶段,我们读取每一行数据,计算出学科和学生的总分。在END阶段,我们首先打印了表尾的格式。而打印总分和计算平均值的简单例子充分体现了awk的工作机制和原理。我希望这个例子能帮助你真正理解awk是如何工作的。小结通过上面的例子,我们了解了awk的工作原理。下面总结一下一些概念和常识点。(一)内置变量1、每行内容记录称为一条记录,英文名称为Record2。每行中用分隔符隔开的每一列称为字段,英文名称为Field。理清了这些概念之后,我们来总结一些重要的Built-in变量:NR:表示当前行数;NF:表示当前列数;RS:行分隔符,默认换行;FS:列分隔符,默认为空格和制表符;OFS:outputcolumnseparator,用于打印时分割字段,默认为空格ORS:outputrowseparator,用于打印时分割记录,默认为换行符语法基本相同。基本用法常用格式化方法:%d十进制有符号整数%u十进制无符号整数%f浮点数%s字符串%c单个字符%e指数形式的浮点数%x%X无符号十六进制整数%0无符号整数表示inoctal%g自动选择合适的表示法\n换行符\t制表符(3)编程语句awk不仅仅是一个Linux命令行工具,它实际上是一种脚本语言。支持所有编程语言的控制结构,它支持:条件语句循环语句数组函数(4)常用函数awk内置了大量有用的函数和函数,还支持自定义函数,让你编写自己的自己的功能来扩展内置功能。下面是一些常用的字符串函数的简要列表:index(s,t)返回子字符串t在s中的位置length(s)返回字符串s的长度split(s,a,sep)拆分字符串,并将分割后的字段存入数组asubstr(s,p,n)根据参数返回子串tolower(s)将字符串转为小写toupper(s)将字符串转为大写这里只是简单总结一下常用的使用过的字符串函数,具体使用方法,还需要参考前面的示例程序,举一反三,应用到实际问题中。本文转载自微信公众号《编程修真》,可通过以下二维码关注。转载本文请联系编程实践公众号。
