awk(1)
从netstat命令中提取了如下信息作为用例$ cat netstat.txtPRoto Recv-Q Send-Q Local-Address Foreign-Address State
tcp000.0.0.0:33060.0.0.0:*LISTEN
tcp000.0.0.0:800.0.0.0:*LISTEN
tcp00127.0.0.1:90000.0.0.0:*LISTEN
tcp00coolshell.cn:80124.205.5.146:18245TIME_WAIT
tcp00coolshell.cn:8061.140.101.185:37538FIN_WAIT2
tcp00coolshell.cn:80110.194.134.189:1032ESTABLISHED
tcp00coolshell.cn:80123.169.124.111:49809ESTABLISHED
tcp00coolshell.cn:80116.234.127.77:11502FIN_WAIT2
tcp00coolshell.cn:80123.169.124.111:49829ESTABLISHED
tcp00coolshell.cn:80183.60.215.36:36970TIME_WAIT
tcp04166coolshell.cn:8061.148.242.38:30901ESTABLISHED
tcp01coolshell.cn:80124.152.181.209:26825FIN_WAIT1
tcp00coolshell.cn:80110.194.134.189:4796ESTABLISHED
tcp00coolshell.cn:80183.60.212.163:51082TIME_WAIT
tcp01coolshell.cn:80208.115.113.92:50601LAST_ACK
tcp00coolshell.cn:80123.169.124.111:49840ESTABLISHED
tcp00coolshell.cn:80117.136.20.85:50025FIN_WAIT2
tcp00:::22:::* LISTEN
下面是最简单最常用的awk示例,其输出第1列和第4例其中单引号中的被大括号括着的就是awk的语句,注意,其只能被单引号包含。其中的$1..$n表示第几例。注:$0表示整个行。$ awk'{print $1, $4}'netstat.txt
Proto Local-Address
tcp0.0.0.0:3306tcp0.0.0.0:80tcp127.0.0.1:9000tcp coolshell.cn:80tcp coolshell.cn:80tcp coolshell.cn:80tcp coolshell.cn:80tcp coolshell.cn:80tcp coolshell.cn:80tcp coolshell.cn:80tcp coolshell.cn:80tcp coolshell.cn:80tcp coolshell.cn:80tcp coolshell.cn:80tcp coolshell.cn:80tcp coolshell.cn:80tcp coolshell.cn:80tcp :::22
我们再来看看awk的格式化输出,和C语言的printf没什么两样:$ awk'{printf "%-8s %-8s %-8s %-18s %-22s %-15s\n",$1,$2,$3,$4,$5,$6}'netstat.txt
Proto Recv-Q Send-Q Local-Address Foreign-Address State
tcp000.0.0.0:33060.0.0.0:*LISTEN
tcp000.0.0.0:800.0.0.0:*LISTEN
tcp00127.0.0.1:90000.0.0.0:*LISTEN
tcp00coolshell.cn:80124.205.5.146:18245TIME_WAIT
tcp00coolshell.cn:8061.140.101.185:37538FIN_WAIT2
tcp00coolshell.cn:80110.194.134.189:1032ESTABLISHED
tcp00coolshell.cn:80123.169.124.111:49809ESTABLISHED
tcp00coolshell.cn:80116.234.127.77:11502FIN_WAIT2
tcp00coolshell.cn:80123.169.124.111:49829ESTABLISHED
tcp00coolshell.cn:80183.60.215.36:36970TIME_WAIT
tcp04166coolshell.cn:8061.148.242.38:30901ESTABLISHED
tcp01coolshell.cn:80124.152.181.209:26825FIN_WAIT1
tcp00coolshell.cn:80110.194.134.189:4796ESTABLISHED
tcp00coolshell.cn:80183.60.212.163:51082TIME_WAIT
tcp01coolshell.cn:80208.115.113.92:50601LAST_ACK
tcp00coolshell.cn:80123.169.124.111:49840ESTABLISHED
tcp00coolshell.cn:80117.136.20.85:50025FIN_WAIT2
tcp00:::22:::* LISTEN
我们再来看看如何过滤记录(下面过滤条件为:第三列的值为0 && 第6列的值为LISTEN)$ awk'$3==0 && $6=="LISTEN"'netstat.txt
tcp000.0.0.0:33060.0.0.0:*LISTEN
tcp000.0.0.0:800.0.0.0:*LISTEN
tcp00127.0.0.1:90000.0.0.0:*LISTEN
tcp00:::22:::* LISTEN
其中的“==”为比较运算符。其他比较运算符:!=, <, < >=, < p>
我们来看看各种过滤记录的方式:
$ awk'$3>0 {print $0}'netstat.txt
Proto Recv-Q Send-Q Local-Address Foreign-Address State
tcp04166coolshell.cn:8061.148.242.38:30901ESTABLISHED
tcp01coolshell.cn:80124.152.181.209:26825FIN_WAIT1
tcp01coolshell.cn:80208.115.113.92:50601LAST_ACK
如果我们需要表头的话,我们可以引入内建变量NR:
$ awk'$3==0 && $6=="LISTEN" || NR==1'netstat.txt
Proto Recv-Q Send-Q Local-Address Foreign-Address State
tcp000.0.0.0:33060.0.0.0:*LISTEN
tcp000.0.0.0:800.0.0.0:*LISTEN
tcp00127.0.0.1:90000.0.0.0:*LISTEN
tcp00:::22:::* LISTEN
再加上格式化输出:
$ awk'$3==0 && $6=="LISTEN" || NR==1 {printf "%-20s %-20s %s\n",$4,$5,$6}'netstat.txt
Local-Address Foreign-Address State0.0.0.0:33060.0.0.0:*LISTEN0.0.0.0:800.0.0.0:*LISTEN127.0.0.1:90000.0.0.0:*LISTEN
:::22:::* LISTEN
内建变量说到了内建变量,我们可以来看看awk的一些内建变量:
$0当前记录(这个变量中存放着整个行的内容)
$1~$n 当前记录的第n个字段,字段间由FS分隔
FS 输入字段分隔符 默认是空格或Tab
NF 当前记录中的字段个数,就是有多少列
NR 已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。
FNR 当前记录数,与NR不同的是,这个值会是各个文件自己的行号
RS 输入的记录分隔符, 默认为换行符
OFS 输出字段分隔符, 默认也是空格
ORS 输出的记录分隔符,默认为换行符
FILENAME 当前输入文件的名字
怎么使用呢,比如:我们如果要输出行号:
$ awk'$3==0 && $6=="ESTABLISHED" || NR==1 {printf "%02s %s %-20s %-20s %s\n",NR, FNR, $4,$5,$6}'netstat.txt011Local-Address Foreign-Address State077coolshell.cn:80110.194.134.189:1032ESTABLISHED088coolshell.cn:80123.169.124.111:49809ESTABLISHED1010coolshell.cn:80123.169.124.111:49829ESTABLISHED1414coolshell.cn:80110.194.134.189:4796ESTABLISHED1717coolshell.cn:80123.169.124.111:49840ESTABLISHED
指定分隔符$ awk'BEGIN{FS=":"} {print $1,$3,$6}'/etc/passwd
root0/root
bin1/bin
daemon2/sbin
adm3/var/adm
lp4/var/spool/lpd
sync5/sbin
shutdown6/sbin
halt7/sbin
上面的命令也等价于:(-F的意思就是指定分隔符)
$ awk-F:'{print $1,$3,$6}'/etc/passwd
注:如果你要指定多个分隔符,你可以这样来:
awk-F'[;:]'
字符串匹配$ awk'$6 ~ /FIN/ || NR==1 {print NR,$4,$5,$6}'OFS="\t"netstat.txt1Local-Address Foreign-Address State6coolshell.cn:8061.140.101.185:37538FIN_WAIT29coolshell.cn:80116.234.127.77:11502FIN_WAIT213coolshell.cn:80124.152.181.209:26825FIN_WAIT118coolshell.cn:80117.136.20.85:50025FIN_WAIT2
$ $ awk'$6 ~ /WAIT/ || NR==1 {print NR,$4,$5,$6}'OFS="\t"netstat.txt1Local-Address Foreign-Address State5coolshell.cn:80124.205.5.146:18245TIME_WAIT6coolshell.cn:8061.140.101.185:37538FIN_WAIT29coolshell.cn:80116.234.127.77:11502FIN_WAIT211coolshell.cn:80183.60.215.36:36970TIME_WAIT13coolshell.cn:80124.152.181.209:26825FIN_WAIT115coolshell.cn:80183.60.212.163:51082TIME_WAIT18coolshell.cn:80117.136.20.85:50025FIN_WAIT2
上面的示例匹配FIN状态, 第二个示例匹配WAIT字样的状态。其实~ 表示模式开始。/ /中是模式。这就是一个正则表达式的匹配。
其实awk可以像grep一样的去匹配第一行,就像这样:
$ awk'/LISTEN/'netstat.txt
tcp000.0.0.0:33060.0.0.0:*LISTEN
tcp000.0.0.0:800.0.0.0:*LISTEN
tcp00127.0.0.1:90000.0.0.0:*LISTEN
tcp00:::22:::* LISTEN
我们可以使用 “/FIN|TIME/” 来匹配FIN 或者TIME :
$ awk'$6 ~ /FIN|TIME/ || NR==1 {print NR,$4,$5,$6}'OFS="\t"netstat.txt1Local-Address Foreign-Address State5coolshell.cn:80124.205.5.146:18245TIME_WAIT6coolshell.cn:8061.140.101.185:37538FIN_WAIT29coolshell.cn:80116.234.127.77:11502FIN_WAIT211coolshell.cn:80183.60.215.36:36970TIME_WAIT13coolshell.cn:80124.152.181.209:26825FIN_WAIT115coolshell.cn:80183.60.212.163:51082TIME_WAIT18coolshell.cn:80117.136.20.85:50025FIN_WAIT2
再来看看模式取反的例子:
$ awk'$6 !~ /WAIT/ || NR==1 {print NR,$4,$5,$6}'OFS="\t"netstat.txt1Local-Address Foreign-Address State20.0.0.0:33060.0.0.0:*LISTEN30.0.0.0:800.0.0.0:*LISTEN4127.0.0.1:90000.0.0.0:*LISTEN7coolshell.cn:80110.194.134.189:1032ESTABLISHED8coolshell.cn:80123.169.124.111:49809ESTABLISHED10coolshell.cn:80123.169.124.111:49829ESTABLISHED12coolshell.cn:8061.148.242.38:30901ESTABLISHED14coolshell.cn:80110.194.134.189:4796ESTABLISHED16coolshell.cn:80208.115.113.92:50601LAST_ACK17coolshell.cn:80123.169.124.111:49840ESTABLISHED19:::22:::* LISTEN