使用AWK或Perl解析SGE的输出(qstat -j“*”)

时间:2013-05-18 03:30:47

标签: linux perl unix awk

我有来自SGE qstat命令的输出,如下所示: http://dpaste.com/1177012/plain/

使用以下命令获取:

 $ qstat -j "*" 

我想要做的是解析qstat -j“*”的输出 表格格式:

#job_number submission_time owner usage
526715       Sat Apr 13 18:43:19 2013 yminakuc cpu=33:04:05:52, mem=2471753193.24440 GBs, io=619.41401, vmem=864.175G, maxvmem=920.232G
....

我正在考虑创建一个可以用作管道的代码:

$ qstat -j "*" | ./mycodeparse.pl 

在AWK或Perl中执行此操作的方法是什么? 或者是否有任何可用的unix工具?

我坚持使用以下构造(逻辑)

 #!/usr/bin/perl -w          
    use strict;                 
    use Data::Dumper;           

    my %hash;                   
    my $curr;

    while ( my $line = <> ) {   
        chomp $line;            


        if ( $line == /^=/ ) {  
           $hash{$line}=$curr = [];
        }
        elsif ( $line =~ /^job_number/ ||
                $line =~ /^owner/ || 
                $line =~ /^usage/ ||
                $line =~ /^submission_time/)) {
           push @$curr,$line;
         }

    }

    print Dumper \%hash ;
    #  Hash print everything instead of selected lines.          

1 个答案:

答案 0 :(得分:1)

该格式非常接近YAML,因此一个选项可以缩小差距:

perl -lne 'BEGIN { print "---" } if (/^=/) { $new = 1; next } if ($new) { s/^/- /; $new = 0 } else { s/^/  / } print' paste > paste.yml

然后正常加载:

#! /usr/bin/env perl
use common::sense;
use YAML 'LoadFile';

die "usage: $0 <file.yml>\n" unless @ARGV == 1;

my %jobs = map { $_->{job_number}, $_ } @{LoadFile(shift)};

say "#job_number submission_time owner usage";
for (keys %jobs) {
  say join("\t", $_, @{$jobs{$_}}{"submission_time", "owner", "usage    1"})
}

由于"usage 1"的丑陋暗示,你可能也想按摩按键。关于names_with_underlines与'带空格的名字'的关键也不同。当然,您可以根据需要键入%jobs哈希值,或者跳过构建它并只处理arrayref:

for (@{LoadFile(shift)}) {
  say join("\t", @{$_}{"job_number", "submission_time", "owner", "usage    1"})
}

输出:

#job_number submission_time owner usage
5276175 Sat Apr 13 18:43:19 2013    yminakuc    cpu=33:04:05:52, mem=2471753193.24440 GBs, io=619.41401, vmem=864.175G, maxvmem=920.232G
606837  Fri Dec 14 19:20:55 2012    ataiba  
6252671 Wed May  8 23:08:22 2013    harukao cpu=9:13:06:40, mem=13115128.89679 GBs, io=19.38717, vmem=16.202G, maxvmem=19.131G

关于您的编辑尝试:基本想法非常合理,但是您在匹配==时犯了一些错误(琐碎错误:=~而不是/^=/;更严重的错误:将你的哈希键在='s的行上,这对于每条记录来说是相同的,结果是你最终只会丢弃最后一条记录)并且你错过了一些技巧:fe存储未处理的记录行而不是将它们分解为键和值。

此更改演示了:将哈希值推送到数组上,并仅为某些键分割线条:

if ( $line =~ /^=/ ) {  
  push @array, $curr = {};
}
elsif ( $line =~ / ^ (job_number
                    | owner
                    | usage
                    | submission_time)
                 .*?: \s* (.+)/x) {
  $curr->{$1} = $2
}

转储输出的摘录:

{
    'usage' => 'cpu=33:04:05:52, mem=2471753193.24440 GBs, io=619.41401, vmem=864.175G, maxvmem=920.232G',
    'owner' => 'yminakuc',
    'job_number' => '5276175',
    'submission_time' => 'Sat Apr 13 18:43:19 2013'
},

只需进行少量更改,您就可以在排除输入后使用任何键将$curr存储到%hash中,或者运行到另一个====行。