一. 概述
awk 是一个强大的文本分析工具.他的工作流程是按行读入文本数据,然后默认以空格分隔切分行数据.然后切分开的部分按照指定的语句进行处理.
其中我们常用的应该是gawk.他是GNU版本的AWK实现.相当于就是一种工具.然后我第一次写是用的mawk,他相当于是awk语言的解释器.这两者我在做题时仅仅遇到了一处不一样的地方,就是对二维数组的支持.
gawk应该是完全支持的,格式如下即可使用:
array_name[i][j]
在mawk中则是以另外一种形式支持二维数组:
array_name[i,j]
这边暂时还是以gawk为主.
二. awk基本说明
这边我个人使用过程中的一个模板是这样的:
awk [-F filed-separator] 'pattern{command}' file-source
其中 -F
指定分隔符,默认是空格.pattern
是匹配原则.{}
中是处理命令,最后则是数据源
有两个特殊的pattern:BEGIN
和 END
.
|
|
BEGIN
是指在读入数据之前匹配成功,所以BEGIN
后接的指令是在读取数据之前执行.可以用来做变量声明以及初始化等等
|
|
END
是指处理完文件后匹配成功.所以后面接的指令是在读取数据完成之后执行的,可用来清理现场或者处理结果
然后有部分内置变量说明下(详细的可去官网查看):
NR 已读取的记录数
NF 记录域的个数
FILENAME 浏览的文件名
针对NF,其中 $n
是用来获取对应域的数据的.不过比较不同的是下标从1开始,0表示的是该行全部数据.
一个最简单的例子:
文件file.txt如下
|
|
|
|
这个就是当读入的数据能和va匹配时就输出第二个域.这里只有evan中含有va
,所以输出的就是12.
其中awk是支持编程的,整体语句规范类似C.
三. 实例
3.1 转置文件
|
|
这个最直观的一个想法就是创建一个二维数组res[NF][NR]
,然后按照每个域输出数据即可.
所以具体代码如下:
|
|
其中如果使用的是gawk的话,res[j,i]
的格式可以写成res[j][i]
上面的代码是为了说明二维数组的使用的,其实还有一种就是一维数组直接存储拼接好的字符串,效率也会更高,代码如下:
|
|
这里代码的意思就是每行进来时,遍历每个域,第i个域就拼到s[i]中,如果是第一行就直接拼接,如果不是第一行就得多加个空格拼接.处理完成之后就是输出了.
3.2 统计词频
|
|
这里我看到的最佳答案是通过pipe拼接多个命令完成的:
|
|
这里代码的意思是:获取文件内容,然后交给tr做字符替换,空格转换为换行,接着升序排序,再交给uniq做去重并统计,统计的结果在交给sort处理成降序,最后交给awk按照第二个域 第一个域
的格式输出.
当然也可以将大部分操作交给awk做:
|
|
这里就是用单词做下标,次数做value来存储数据,然后按照第二个pos倒序排列.