之前更新了linux初探Json
处理工具之jq
,发现挺有意思的,索性将awk
、grep
、sed
等都给总结一下。
什么是awk
这里的awk
,在linux
系统下,我们一般指的是gawk
,是GUN
利用awk
来创建的一门编程语言,符合POSIX 1003.1
标准,主要是用于文字处理,为此我们简称awk
,在linux
系统中,一般替我们做了软连接,我们可以通过whereis
一路找下去,即可找到gawk
或者其他版本的awk
。
并不是所有的
linux
系统都是预装了gawk
的
我们为什么需要awk
对于有取相应列需求的,我们使用awk
在合适不过了,这也是使用awk
最多的操作之一,这里,我们举了一个不是例子的例子,因为要证明一个东西确实被“需要”,是很困难的,没有什么是不可替代的。
需求分析
我们准备一个文本信息,我们想取出其中黄色部分勾选出来的内容
shell脚本
我们先使用shell
脚本来写这个需求,具体流程为
- 先读取一行
- 以空格为分割,获取行数有多少列
- 输出最后一列
根据需求分析,我们很快便顺利编写了脚本
我们执行脚本查看结果
awk命令
我们将上述操作,使用awk
来写,仅需一句 awk '{print $NF}'
即可,具体逻辑,我们在案例中讲解。
希望通过这个例子,能够了解,我们为什么要学习使用awk
,不仅是因为可以在同事面前装一波,更重要的是能够节省大量的时间。
awk工作流程
当我们想获取某个文件,假设以空格分开,获取第多少列,这个时候,就非awk
莫属了,它的工作流程简单梳理,可以理解为如下模式。
其实我们将awk
分为3个块,分别是 BEGIN
语句块、END
语句块 和 主体语句块 , 其具体工作流程如下
- 执行
BEGIN
语句块 - 重复从文件/标准输入中读取一行,执行
pattern
语句块,直至文件结尾/标准输入结束 - 最后执行
END
语句块
其语法如下
BEGIN { # BEGIN 语句块 } { # 主体语句块 print $0 } END { # END 语句块 }
其中,BEGIN
和END
语句块可以被忽略。
从最简单开始
awk内置变量
$num
: 每行获取的num
列,若为0,则代表整行
FS
: 自定义分隔符,在命令行,可以使用-F
来指定
NF
: 列数量
NR
: 行数
提取文档的第一列
例如上面的文案,我们想提取文档的第一列出来
在awk
中,我们使用$
来取具体的列,比如 第一列: $1
,第二列$2
,以此类推。
要输出第一列,我们使用print
即可。
很轻松,我们可以顺利用命令写出求出第一列
命令: awk '{print $1}'
这个命令就是我们忽略了BEGIN
以及END
,我们补充完整是这样的。
我们使用awk -f
来从文件读取awk
指定且运行指令。
指定分隔符
在awk
中,默认是以空格作为分隔符,但是我们可以指定自定义分隔符,例如我们想获取/etc/passwd
中的用户名,但是该文件是以:
作为分割的,文件内容如下:
在进行awk
切割中,我们使用FS
作为指定自定义分隔符,该操作需要定义在BEGIN
语句块中,我们编写下awk
指令
我们使用命令行,则可以使用-F
来指定分隔符,例如:
这里提及一点,若有多个分隔符,可以使用-F=[]
来定义,若我们即想设置:
为分隔符,又想设置空格为分隔符,即可设置为-F=[. ]
读取文档最后一列
我们可以使用NF
变量,读取文档最后一列,我们同样拿/etc/passwd
为例,我们想获取用户的默认shell
即以:
分割的最后一列
我们可以使用命令awk -F ":" '{print $NF}'
来获取
$NF
的具体逻辑是什么呢?
NF
是awk
的内置变量,其记录了该行按照预设的分隔符进行划分,其记录的具体列数,将值放入NF
中,而使用$num
获取第num
列的数据,而该num
我们代入NF
则是最后一列。
我们通过例子说明
通过案例,我们可以验证,NF
仅仅是记录了该行按照预设定义的分隔符进行分割后的列数。
给文件前增加一个行号
NR
是记录awk
处理的行数,我们可以使用该内置变量来打印行数,例如:
我们还是使用pdudo_awk_test.txt
为案例,打印一下行数
命令: awk '{print NR": "$0}'
NR
内置变量作用不止于此,例如,我们可以处理第100
行到120
行,就可以使用NR
进行控制。
总结
在文章中,我们了解了什么是awk
,以及谈论了一下我们为什么需要awk
,总之,在列文本处理这块awk
非常棒,而后在一些案例中,我们也看到了比较简单的awk
操作,awk
不仅是命令行,也是一门编程语言,所以也有其条件判断if
、以及循环for
等,我们后期再介绍。