替换s /// in循环中的变量不会改变?为什么?

时间:2012-08-31 00:23:00

标签: perl

这让我疯了。帮助

在我看来,在Perl foreach循环中,替换模式之外的变量会按预期变化,但替换模式中的变量会“卡住”。这几乎就像perl在s///代码块中遇到foreach替换模式一样,它会在第一次循环时插入替换模式内容,而不会再次插入。

以下是一些测试代码:

#!/usr/bin/perl

@replacements=("a", "b", "c");
@input=("xxletterxx");

foreach $replacement (@replacements) {
        foreach $line (@input) {
                $line=~s/xxletterxx/$replacement/g;
                print "R: $replacement\n";
                print "L: $line\n";
        }
}

我认为它应该打印出来:

R: a   
L: a   
R: b   
L: b   
R: c   
L: c

...而是打印出来:

R: a  
L: a  
R: b  
L: a  <--- Why isn't this 'b'?  
R: c  
L: a  <--- Why isn't this 'c'?  

注意“L”值在替换模式中仍然是“a”,即使代码块中的其他地方正在改变@replacements的成员?

为什么?

我觉得Perl突然坏了,或者我已经失去了理智。

在perl中似乎发生了this DOS behavior

3 个答案:

答案 0 :(得分:6)

此循环控件:

foreach $line (@input)

$line的每个元素添加@input别名,因此您第一次进行替换时,不仅更改了$line,还更改了$input[0]。之后,xxletterxx消失了,所以不再发生替换,因为/xxletterxx/不匹配。

要使其按照您想要的方式工作,您需要通过迭代@input数组的克隆来打破别名:

foreach $line (@{[@input]})

或者在修改之前将$line复制到另一个变量,在循环体中将$line视为只读:

foreach $line (@input) {
        $modifiedline = $line;
        $modifiedline=~s/xxletterxx/$replacement/g;
        print "R: $replacement\n";
        print "L: $modifiedline\n";
}

答案 1 :(得分:0)

没有xxletterxx替换为bc,因为您已将其替换为a

答案 2 :(得分:0)

正如hobbs所说,问题是一旦你用xxletterxx取代a,模式就不再匹配,因此不会发生替换。我不确定你的最终目标是什么,但这是有效的

#!/usr/bin/env perl

use warnings;
use strict;

my @replacements=("a", "b", "c");

foreach my $replacement (@replacements) {
  my $line = "xxletterxx";
  $line=~s/xxletterxx/$replacement/g;
  print "R: $replacement\n";
  print "L: $line\n";
}

就像这样

#!/usr/bin/env perl

use warnings;
use strict;

my @replacements=("a", "b", "c");
my @lines = ("xxletterxx") x 3;

foreach my $replacement (@replacements) {
  my $line = shift @lines;
  $line=~s/xxletterxx/$replacement/g;
  print "R: $replacement\n";
  print "L: $line\n";
}

此外我已为您添加了strictwarnings: - )

编辑:一个可能更有趣的例子是对最后一个的修改,对于每个替换尝试依次更改@lines的每个元素,并在替换成功后停止。

#!/usr/bin/env perl

use warnings;
use strict;

my @replacements=("a", "b", "c");
my @lines = ("xxletterxx") x 3;

foreach my $replacement (@replacements) {
  foreach my $line (@lines) {
    last if $line=~s/xxletterxx/$replacement/g;
  }

  print "R: $replacement\n";
  print "A: @lines\n";
}
相关问题