除了 grep
命令外,Linux操作系统中还有两个不得不的掌握的工具--- awk
和 sed
。grep
适用于从文件或终端输出中匹配指定模式的行内容, awk
作为一个文本处理工具,在处理表格类的文本是显得更加得心应手,而 sed
则更关注于针对文本完成复杂的编辑功能。
awk
是一种操作数据和生成报告的脚本语言,通过在所接收到的文本文件中逐行匹配模式并完成指定操作的功能。在 awk
表达式中,你可以自己定义使用变量、函数、字符串函数和逻辑运算符。
语法
awk [options] 'selection_criteria {action}' input-file > output-file
在 awk
支持的options中,如下是其中最常用的两个
- -F fs: 使用出入的字段作为分割符
- -f program-file: 使用出入的文件代替输入的第一个命令行参数
在 awk
中常用的内置变量
- FS: (输入)字段分割符。默认为空格
- NF: awk对输入文件处理时会使用逐行处理的方式,NF 为使用分割符对行内容进行切分后的域(字段)
- NR: 使用时会输出在输入文件的每行前加上行号
- RS: 指定输入记录的每行的分割符,默认RS为"\n"
- OFS: (输出)字段分割符。默认为空格
- ORS: 指定输出记录的每行的分割符。默认ORS为"\n"
- BEGIN: 执行指定前先执行BEGIN变量后定义的语句
- END: 执行指令后执行END变量后定义的语句
- if: 使用if条件判断。格式为 '{ if(xx==xx) print xx; }'
用法
以下示例多会使用Linux操作系统上的用户文件/etc/passwd
,以如下内容为例
#cat < /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
- 默认情况下awk会逐行扫描输入文件,并输出文件的所有内容
# awk '{ print }' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
- 指定分隔符':',输出用户文件的用户名及登录所使用的终端
# awk -F':' '{ print $1,$NF }' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
- 匹配指定模式的内容并输出切分后的指定域
注意: NF 与 NF 表示第几域的内容
# awk -F':' ' /root/ { print $1,$NF }' /etc/passwd # 匹配用户文件中包含root的行,并根据分割符切分出指定的域,输出第一个域和最后一个域
root /bin/bash
# awk -F':' ' /root/ { print $1,NF }' /etc/passwd
root 7
- 指定分割符':',并输出第一个域及对应的行号
# awk -F':' '{ print NR,$1 }' /etc/passwd
1 root
2 bin
3 daemon
4 adm
- 指定分割符':',输出用户文件中对应用户名、用户id、组id、登录后使用的终端对应的第一、三、四、七域
# awk -F':' '{ print $1,$3,$4,$7 }' /etc/passwd
root 0 0 /bin/bash
bin 1 1 /sbin/nologin
daemon 2 2 /sbin/nologin
adm 3 4 /sbin/nologin
- 指定(域)分割符':',并指定每行记录的分割符'****\n'输出用户文件的第一域
# awk -F':' ' RS="****\n" { print $1,RS }' /etc/passwd # 在这里, RS="****\n" 实际上在输出的域之后加上了 ****,\n 则为换行
root ****
bin ****
daemon ****
adm ****
- 指定(域)分割符':',输出指定多少行的记录
# awk -F':' ' NR==2,NR==4 { print NR,$1 }' /etc/passwd # 输出2,3,4 行的第一域
2 bin
3 daemon
4 adm
# awk -F':' ' NR > 1,NR < 4 { print NR "\t" $1 }' /etc/passwd # \t 为制表符
2 bin
3 daemon
4 adm
- 输出文件的行记录
# awk -F':' ' END { print NR }' /etc/passwd
4
- 执行指令前后添加输出
# awk -F':' ' BEGIN { print ">>>>>>>>>>>"} { print NR } END { print "<<<<<<<<<<<<" } ' /etc/passwd
>>>>>>>>>>>
1
2
3
4
<<<<<<<<<<<<
# awk -F':' ' BEGIN { for(i=1;i<=5;i++) print "The num is: "i } ' /etc/passwd
The num is: 1
The num is: 2
The num is: 3
The num is: 4
The num is: 5
- 输出时指定输出行的域分割符
# awk -F':' ' OFS="\t" { print $1,$NF }' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
- 输出时指定输出记录的分割符
# awk -F':' ' ORS="\n>>>>\n" { print $1,$NF }' /etc/passwd # 每一行为一条记录,因此会在行后输出">>>>\n"
root /bin/bash
>>>>
bin /sbin/nologin
>>>>
daemon /sbin/nologin
>>>>
adm /sbin/nologin
>>>>
- 使用if条件输出匹配的行
# awk -F':' ' { if($1=="root") print $0; } ' /etc/passwd
root:x:0:0:root:/root:/bin/bash
# awk -F':' ' { if($4>3) print $0; } ' /etc/passwd
adm:x:3:4:adm:/var/adm:/sbin/nologin
- 输出每行记录的长度
# awk -F':' '{ print length($0) }' /etc/passwd # $0 为每行的所有域
31
32
39
36
参考:
https://www.geeksforgeeks.org/awk-command-unixlinux-examples/
http://c.biancheng.net/view/4082.html