这让我疯了。帮助
在我看来,在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。
答案 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
替换为b
或c
,因为您已将其替换为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";
}
此外我已为您添加了strict
和warnings
: - )
编辑:一个可能更有趣的例子是对最后一个的修改,对于每个替换尝试依次更改@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";
}