之前我对awk的使用仅限于从格式确定的字符串输出中取出自己相要的字段。但是最近有一个需求,需要从标准输出中截取一个字段,但是这个标准输出看上去好像格式并不统一:
这个命令就是top -bn 1 -i -c
输出如下:
top - 12:23:08 up 16 days, 20:30, 6 users, load average: 1.20, 1.17, 0.80
Tasks: 287 total, 1 running, 286 sleeping, 0 stopped, 0 zombie
%Cpu(s): 2.4 us, 6.9 sy, 0.0 ni, 90.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 32945412 total, 22137276 free, 8835848 used, 1972288 buff/cache
KiB Swap: 1044476 total, 1044476 free, 0 used. 23118824 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
20491 user 20 0 42948 3520 2872 R 5.9 0.0 0:00.01 top -bn 1 -i -c
我需要获取cpu占用率达到一定值的进程的PID。也就是说,我只关注top命令的第二部分:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
20491 user 20 0 42948 3520 2872 R 5.9 0.0 0:00.01 top -bn 1 -i -c
如果只是单纯地用 top -bn 1 -i -c |grep PID | awk '{print $1}'
这样的命令似乎没有办法优雅地达到我的目的。
我想过,在grep的时候,获取命中行的下面N行,但是我永远无法知道这个N等于多少。
我觉得awk就是linux字符处理工具里的瑞士军刀,它肯定可以。
awk是可编程的
其实 awk '{print $}'
这个命令中,''
中的部分是一个脚本,而且不仅在awk命令后面可以有脚本,在awk命令之前也可以写一些脚本。这些脚本的用途就是对awk的输入做一些预先的处理,或者过滤。
根据这个思路,再回到我的需求:cpu占用率达到一定值的进程的PID,我写出了这条命令:
top -bn 1 -i -c |awk '{ if (NR > 6) print }' |awk '{ if ($9 > 99) print $1,$9}'
第一个if
过滤掉了top命令的上半部分;第二个if
筛选出了我想要的PID。
awk的内置变量
awk之所以可以高效地获取字段,是因为内置了很多变量,灵活运用这些变量,可以让这把瑞士军刀发挥它最大的功效:
NR:我的理解就是number of record,已处理的输入记录数
NF:我的理解就是number of field,数据文件中的字段总数
FS:输入字段分割符 field seperator
RS:输入记录分割符 record seperator
最后推荐一本书:《Linux命令行与shell脚本编程大全 第3版 ,布鲁姆 ,P606.pdf》