脱掉外套

过滤记录

我们再来看看如何过滤记录(下面过滤条件为:第三列的值为0 && 第6列的值为LISTEN)

  1. $ awk '$3==0 && $6=="LISTEN" ' netstat.txt
  2. tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN
  3. tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
  4. tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN
  5. tcp 0 0 :::22 :::* LISTEN

其中的“==”为比较运算符。其他比较运算符:!=, >, <, >=, <=

我们来看看各种过滤记录的方式:

  1. $ awk ' $3>0 {print $0}' netstat.txt
  2. Proto Recv-Q Send-Q Local-Address Foreign-Address State
  3. tcp 0 4166 coolshell.cn:80 61.148.242.38:30901 ESTABLISHED
  4. tcp 0 1 coolshell.cn:80 124.152.181.209:26825 FIN_WAIT1
  5. tcp 0 1 coolshell.cn:80 208.115.113.92:50601 LAST_ACK

如果我们需要表头的话,我们可以引入内建变量NR:

  1. $ awk '$3==0 && $6=="LISTEN" || NR==1 ' netstat.txt
  2. Proto Recv-Q Send-Q Local-Address Foreign-Address State
  3. tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN
  4. tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
  5. tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN
  6. tcp 0 0 :::22 :::* LISTEN

再加上格式化输出:

  1. $ awk '$3==0 && $6=="LISTEN" || NR==1 {printf "%-20s %-20s %s\n",$4,$5,$6}' netstat.txt
  2. Local-Address Foreign-Address State
  3. 0.0.0.0:3306 0.0.0.0:* LISTEN
  4. 0.0.0.0:80 0.0.0.0:* LISTEN
  5. 127.0.0.1:9000 0.0.0.0:* LISTEN
  6. :::22 :::* LISTEN

内建变量

说到了内建变量,我们可以来看看awk的一些内建变量:

$0当前记录(这个变量中存放着整个行的内容)
$1~$n当前记录的第n个字段,字段间由FS分隔
FS输入字段分隔符 默认是空格或Tab
NF当前记录中的字段个数,就是有多少列
NR已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。
FNR当前记录数,与NR不同的是,这个值会是各个文件自己的行号
RS输入的记录分隔符, 默认为换行符
OFS输出字段分隔符, 默认也是空格
ORS输出的记录分隔符,默认为换行符
FILENAME当前输入文件的名字

怎么使用呢,比如:我们如果要输出行号:

  1. $ awk '$3==0 && $6=="ESTABLISHED" || NR==1 {printf "%02s %s %-20s %-20s %s\n",NR, FNR, $4,$5,$6}' netstat.txt
  2. 01 1 Local-Address Foreign-Address State
  3. 07 7 coolshell.cn:80 110.194.134.189:1032 ESTABLISHED
  4. 08 8 coolshell.cn:80 123.169.124.111:49809 ESTABLISHED
  5. 10 10 coolshell.cn:80 123.169.124.111:49829 ESTABLISHED
  6. 14 14 coolshell.cn:80 110.194.134.189:4796 ESTABLISHED
  7. 17 17 coolshell.cn:80 123.169.124.111:49840 ESTABLISHED

指定分隔符

  1. $ awk 'BEGIN{FS=":"} {print $1,$3,$6}' /etc/passwd
  2. root 0 /root
  3. bin 1 /bin
  4. daemon 2 /sbin
  5. adm 3 /var/adm
  6. lp 4 /var/spool/lpd
  7. sync 5 /sbin
  8. shutdown 6 /sbin
  9. halt 7 /sbin

上面的命令也等价于:(-F的意思就是指定分隔符)

$ awk -F: '{print $1,$3,$6}' /etc/passwd

注:如果你要指定多个分隔符,你可以这样来:

awk -F '[;:]'

再来看一个以\t作为分隔符输出的例子(下面使用了/etc/passwd文件,这个文件是以:分隔的):

  1. $ awk -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd
  2. root 0 /root
  3. bin 1 /bin
  4. daemon 2 /sbin
  5. adm 3 /var/adm
  6. lp 4 /var/spool/lpd
  7. sync 5 /sbin