使用正则表达式将awk单行连接到perl(汇总数据组)

时间:2017-12-06 00:26:22

标签: regex perl awk

给出以下输入:

£ cat problem
  Team 7
  John: 19
  Sue: 20
  Pam: 35
  Team 42
  Jeff: 12
  Sam: 3
  Phil: 26
  Jill: 10
  Team 9
  Bill: 19
  John: 7
  Linda: 15

我试图在perl one-liner中重现以下输出:

£ awk '/Team/ {x=$2} /: *[0-9]+/ {myarray[x]+=$2}; END{for (key in myarray) {print "Team " key ": " myarray[key]}}' problem
Team 42: 51
Team 7: 74
Team 9: 41

这个(基本)问题和数据实际上来自perl教程。 http://learnperl.scratchcomputing.com/tutorials/csss/

我对接近这个的东西很感兴趣,我试过了......实际上超过50种变体:

 £ perl -e 'while(<>){if (/Team/){$x = /(\d+)/;}else{/(\d+)/;$myarray{$x}+= {$1}; }} foreach $key (keys %myarray){print "$key\n";}' problem

我知道1)这些正则表达式没有返回匹配(+= {$1}试图解决这个问题),2)即使它们是我可能错误地填充哈希。谷歌搜索潜在的解决方案返回详细,多行代码。我还在等待按键输出正确,然后才打算转移到值上,顺便说一下。

1 个答案:

答案 0 :(得分:5)

不检查awk代码,我就写下这个perl:

perl -lne '
        if (/Team (\d+)/) {
            $t = $1;
        } elsif (/: (\d+)/) {
            $score{$t} += $1
        }
    } END {
        printf "Team %d: %d\n", $_, $score{$_} for keys %score
' problem
Team 7: 74
Team 9: 41
Team 42: 51

-n选项隐含地围绕给定代码包装while (<>) {...}循环。有关所有详细信息,请参阅perldoc perlrun

} END {位利用了这个,并允许你在while循环中收集数据,然后在循环完成时用它做任务。

您可以通过添加-MO=Deparse选项来了解perl如何处理单行:

perl -MO=Deparse -lne '
        if (/Team (\d+)/) {
            $t = $1;
        } elsif (/: (\d+)/) {
            $score{$t} += $1
        }
    } END {
        printf "Team %d: %d\n", $_, $score{$_} for keys %score
' problem
BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    if (/Team (\d+)/) {
        $t = $1;
    }
    elsif (/: (\d+)/) {
        $score{$t} += $1;
    }
}
sub END {
    printf "Team %d: %d\n", $_, $score{$_} foreach (keys %score);
}
-e syntax OK

我不确定为什么它会将END块变成子程序。

关于您的代码的几点说明:

  1. 使用更好的变量名。

  2. $x = /(\d+)/

  3. ($x) = /(\d+)/; # with parentheses on the left-hand side

    • 当您使用$myarray{$x}+= {$1}作为表达式时,您正在创建哈希引用
    • 在这种情况下{...},您的哈希没有足够的元素:它需要偶数编号的键值对列表。
    • 你只想要{$1}
  4. $myarray{$x} += $1

    • 迭代哈希的另一种方法是在while循环中使用foreach $key (keys %myarray){...}函数:

      each