perl:重构 s/.../.../g -> while {}?

perl: refactor s/.../.../g -> while {}?

我有一个可怕的 eval-substitution;这是一个简化版本

$ perl -wpe 's@(for )(\w+)@ . "user " . qx/id /@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()?

这个成语是用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;

curlies的优点是可以嵌套。