更高效的正则表达式来解析linux top命令值

时间:2014-06-04 15:36:30

标签: regex linux perl optimization

我试图在这个脚本的每个进程级别上获取一些测量值。查看我正在寻找的值的最简单方法是只获取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*8364\s+([^\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]+)模式的方法。

无论如何,感谢您花时间阅读本文!

干杯

4 个答案:

答案 0 :(得分:1)

我不知道你是否已经限制在Perl之外,或者只是为此写了一个简单的脚本。在第二种情况下,您可以使用awk,在这种情况下它是直接的:

{
    if ($1 == <process_value_here>)
    {
        print $1 /* Pid*/ "," $2 /*user*/ ...
    }
}
默认情况下,

awk会按空格分割输入,因此您可以直接访问$xx是字段的编号。

答案 1 :(得分:1)

在有分隔符时使用拆分

my @cols = split ' ', ( $top_string =~ /(\d.+)/ )[0];

答案 2 :(得分:1)

如前所述,只需使用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 "@cols\n" 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

答案 3 :(得分:0)

认为这是一个有些温和的反应,但这是我的一个宠儿。我看到Linux上有很多人想要在程序中获取有关特定PID的信息,而忽略了/ proc目录的存在。当然它是为这种事物创建的(以程序方式提取有关特定过程的信息)。

为了从&#39; Top&#39;中获取信息你需要调用外部程序,它需要一个fork和所有后续代码来管理那个分支 - 也许它在Perl中很容易,但是我已经习惯了C和C在那里有更多的开销然后我想要处理用。然后你必须编写一个正则表达式(排队引用&#39;现在你有两个问题&#39;)来解析输出。

直接从/ proc / entry读取只需要标准文件IO,并且/ proc的输出设计为以编程方式解析,因此不需要复杂的RExp来处理它。

Linux上的顶部从/ proc内部读取以获取其信息 - 所以我无法看到一个很好的理由不在这里切断中间人。我唯一能想到的就是便携性,因为有些* Nixs没有/ proc目录。但是再一次,Top输出的可移植性如何(BSD top和GNU top无论如何都可能略有不同)。