我试图在我正在编写的这个脚本中获取每个进程级别的一些测量值。查看我正在寻找的值的最简单方法是获取top
命令的输出。
所以当我尝试解析它时,我的正则表达式看起来有点可笑。给定这个输出:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8364 cgroup_t 20 0 764m 646m 1520 R 101.7 4.3 0:05.51 perl
我想出了一个正则表达式来获取一些值(8364被传递到一个var上,为了便于阅读,在这里显示,顶部输出存储在一个名为$top_string的var上):
if($top_string =~ m/^s*8364s+([^s]+)s+([^s]+)s+([^s]+)s+([^s]+)s+([^s]+)s+([^s]+)s+([^s]+)s+([^s]+)s+([^s]+)s+([^s]+)s+([^s]+)/){
#return desired var number, ie. $1,$2...etc
}
这是有效的,但似乎有点过头了。有什么办法能更有效地做到这一点吗?我觉得我可能记得一种避免反复输入s+([^s]+)
模式的方法。
欢呼
使用分隔符
my @cols = split ' ', ( $top_string =~ /(d.+)/ )[0];
我不知道您是否受到Perl的限制,或者只是为此编写了一个简单的脚本。在第二种情况下,您可以使用awk
,在这种情况下,它是直接的:
{
if ($1 == <process_value_here>)
{
print $1 /* Pid*/ "," $2 /*user*/ ...
}
}
awk
默认情况下通过空格分割输入,因此您可以直接访问$x
, x
是字段的编号。
正如已经说过的,只使用split
。但是,一个技巧是将列数限制为12,因为top命令中的最后一列可以包含空格。
use strict;
use warnings;
my $top_string = do { local $/; <DATA> };
for my $line (split "n", $top_string) {
my @cols = split ' ', $line, 12;
print "@colsn" if $cols[0] =~ /^8364$/;
}
__DATA__
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8364 cgroup_t 20 0 764m 646m 1520 R 101.7 4.3 0:05.51 perl
认为这是一个有点天真的回答,但这是我最讨厌的事情。我看到很多Linux上的人想要获得关于他们程序中特定PID的信息,而忽略了/proc目录的存在。当然,它就是为这种事情而创建的(以编程方式提取有关特定进程的信息)。
为了从'Top'中获取信息,你需要调用外部程序,这需要一个分支和所有后续代码来管理该分支-也许在Perl中很容易,但我习惯了C,在C中这是更多的开销,然后我想处理。然后,您必须编写一个正则表达式(将引号"现在您有两个问题"排队)来解析输出。
直接从/proc/条目中读取只需要标准的文件IO,并且/proc的输出被设计为以编程方式解析,因此不需要复杂的RExp来处理它。
Linux上的Top从/proc内部读取它的信息——所以我找不到一个不去掉中间人的好理由。我唯一能想到的是可移植性,因为一些* nix没有/proc目录。但是Top输出的可移植性(BSD Top和GNU Top可能有细微的不同)。