给出以下输入:
£ 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)即使它们是我可能错误地填充哈希。谷歌搜索潜在的解决方案返回详细,多行代码。我还在等待按键输出正确,然后才打算转移到值上,顺便说一下。
答案 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块变成子程序。
关于您的代码的几点说明:
使用更好的变量名。
$x = /(\d+)/
要将捕获的文本分配给变量,您必须在左侧有一个列表上下文:m//
,所以
($a, $list, $of, $variables) = (a, list, of, values)
($x) = /(\d+)/; # with parentheses on the left-hand side
$myarray{$x}+= {$1}
作为表达式时,您正在创建哈希引用 {...}
,您的哈希没有足够的元素:它需要偶数编号的键值对列表。{$1}
$myarray{$x} += $1
迭代哈希的另一种方法是在while循环中使用foreach $key (keys %myarray){...}
函数:
each