首页 > 解决方案 > perl:重构 s/.../.../g -> 而 {}?

问题描述

我有一个可怕的评估替代;这是一个简化版本

$ perl -wpe 's@(for )(\w+)@$1 . "user " . qx/id $2/@ge'

它取代了例如

Stats for root are bad
Stats for user uid=0(root) gid=0(root) groups=0(root)
 are bad

是否有将 s/.../.../g 变成循环的习语?就像是

while (m@(for )(\w+)@) {
  # explicitly replace match with expression computed over several LOCs 
}

或者也许以某种方式使用 map()?

标签: regexperlmap-function

解决方案


这个成语是用s///eg。不可否认,它比您正在寻找的替代方案更好。

s{pat}{ repl }eg;

相当于

my $out = '';
my $last_pos = 0;
while (m{pat}g) {
   $out .= substr($_, $last_pos, $-[0] - $last_pos) . do { repl };
   $last_pos = $+[0];
}

$_ = $out . substr($_, $last_pos);

因为您暗示在替换表达式中将执行多个语句,所以我将您的代码编写如下:

s{for \K(\w+)}{
   ...
   ...
}eg;

curly 的优点是它们可以嵌套。


推荐阅读