从最后但一行打印特定字段

时间:2014-01-09 09:08:02

标签: perl bash awk

我正在尝试解析此输出:

$ top -b -d 1 -n 1 -p 5997
top - 08:54:39 up 86 days,  2:42,  1 user,  load average: 0.00, 0.03, 0.05
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
Cpu(s):  8.9%us,  1.5%sy,  0.0%ni, 89.5%id,  0.1%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   3869696k total,  2010912k used,  1858784k free,   162404k buffers
Swap:        0k total,        0k used,        0k free,   736120k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 5997 tomcat7   20   0 1209m 534m 6940 S  0.0 14.2  14:40.85 java

$

我的预期输出是:

534m 

所以我想从6th获取second last line字段。 (最后一行是一个空行,因此我正在查看second last行)

这是我的解决方案:

$ top -b -d 1 -n 1 -p 5997 | awk 'NF > 0' | awk 'END {print $6}'
539m

我首先删除空白行,然后从最后一行中提取第6个字段。它有效。完美!!!

问题:

我不喜欢使用 2 awk管道。因此,必须有一个优雅的解决方案,使用单个awk语句来实现相同的目标。你能帮帮我吗?

即使是Perl oneliner也会有所帮助。

5 个答案:

答案 0 :(得分:5)

你当然可以结合top和awk来获得你想要的任何文本部分。但是根据您的要求,我认为ps更适合您:

ps -h --format rss <PID>

这会在Kilobytes中为您提供相同的号码。如果您希望最后m,则可以/1024

编辑

即使Jonta报告了版本差异问题。我仍然不认为解析top的输出以获得内存使用是最好的方法。这将是通用的解决方案:

grep -oP 'VmRSS:\s*\K.*' /proc/<PID>/status 

这是我的输出,只有上面的命令和ps一个:

kent$  ps -h -o rss 25579                             
405304

kent$  grep -oP 'VmRSS:\s*\K\d*' /proc/25579/status 
405304

如果您愿意,可以轻松地将grep替换为其他功能强大的工具,例如bc,awk ...以获得mb单位。

答案 1 :(得分:2)

你走了:

awk 'now { print $6; exit } $1 == "PID" { now = 1 }'

说明:

  • 为每行输入
  • 评估命令
  • 未设置变量now,因此默认情况下不会执行now { ... }的块
  • 当第一个字段为“PID”时,我们将now设置为1,这样当下一行到来时,now { ... }块将被执行
  • now { ... }块中,我们打印第6个字段并退出以停止处理

答案 2 :(得分:1)

top -b -d 1 -n 1 -p 5997 | perl -anE '@r=@F if @F; END{ say $r[5] }'

perl遍历行并在@F中存储列值。它还将相同的值存储到@r数组中,但仅在存在实际值时(对于非空行)。 在最后一个非空行的结束输出列。

答案 3 :(得分:1)

以下是我使用awk

完成此操作的方法
awk '/PID/ {getline;print $6}'

这将搜索PID行,获取下一行并打印字段$6

答案 4 :(得分:0)

获得倒数第二行的简单(但一般)方法:

$ echo -e "abc\ndef\nijk" | tail -2 | head -1