sub summs_by_key {
foreach my $R (@CURR_RECS) {
if ($combine) {
print __LINE__ . ") ... $R" ;
$R =~ s/\^/\|/ for 1 .. $KEY_POS ; # the regex expression
print __LINE__ . ") ___ $R" ;
}
#... etc
}
#... etc // no other reassingments of $R
}
Run Code Online (Sandbox Code Playgroud)
注意: @CURR_RECS 是一个声明为的全局数组,our @CURR_RECS ;
它在单独的子/函数中填充。正则表达式的更改实际上可以更改数组值。该函数被调用多次,在后续调用中,我们注意到正则表达式的更改已作用于数组的元素。
我的问题是这是正常行为还是 Perl 错误 - 它仅在正则表达式行执行 2 次而不是一次时发生(即 $KEY_POS = 2)
我通过不直接使用迭代器而是使用它的“副本”来解决这个问题。我将迭代器重命名为 $Rs 并将其分配给 $R。
foreach my $Rs (@CURR_RECS) {
my $R = $Rs ;
if ($combine) {
print __LINE__ . ") ... $R" ;
$R =~ s/\^/\|/ for 1 .. $KEY_POS ;
print __LINE__ . ") ___ $R" ;
}
# ... etc
}
Run Code Online (Sandbox Code Playgroud)
@CURR_RECS 包含
sub summs_by_key {
foreach my $R (@CURR_RECS) {
if ($combine) {
print __LINE__ . ") ... $R" ;
$R =~ s/\^/\|/ for 1 .. $KEY_POS ; # the regex expression
print __LINE__ . ") ___ $R" ;
}
#... etc
}
#... etc // no other reassingments of $R
}
Run Code Online (Sandbox Code Playgroud)
其中插入号是字段分隔符。如果 $combine 为 true,那么我们想要组合前这么多字段...这就是正则表达式所完成的...通过将如此多的 ($KEY_POS) 分隔符更改为其他内容 - 更改为“|”。这些是正则表达式条目之前和之后的内容:
foreach my $Rs (@CURR_RECS) {
my $R = $Rs ;
if ($combine) {
print __LINE__ . ") ... $R" ;
$R =~ s/\^/\|/ for 1 .. $KEY_POS ;
print __LINE__ . ") ___ $R" ;
}
# ... etc
}
Run Code Online (Sandbox Code Playgroud)
然而,当再次执行相同的函数时,传入的元素与第一次运行时不同......但已根据正则表达式进行了修改。前导 126) ...和127) ___ 不是数组的一部分,它们是代码的行号。在第二次调用该函数时,我们可以看到传入的元素显示了先前调用移动的插入符号。
2x^szo_p^230414:01:43^0^0^
3x^cold^230309p^0^0^QQ.y
3x^szo_p^230419:14:51^-10^6^
4x^cold^230320^0^60^
4x^front^230418:16:36^20^40^
4x^sky^230403^0^0^
4x^szo_r^230419:14:46^-5^23^
6g^szo_p^230309^0^8^
6x^cup^230417:05:04^2^4^
6x^r_l^230402^0^40^
Run Code Online (Sandbox Code Playgroud)
佩尔辛:
如果 LIST 的任何元素是左值,则可以通过修改循环内的 VAR 来修改它。相反,如果 LIST 的任何元素不是左值,则任何修改该元素的尝试都将失败。换句话说,foreach 循环索引变量是您要循环的列表中每个项目的隐式别名。
所以是的,循环迭代器不是副本,而是别名。
my @a = 1..3;
++$_ for @a;
say "@a"; # "2 3 4"
Run Code Online (Sandbox Code Playgroud)
以下是制作副本的稍微简单的方法:
for ( @CURR_RECS ) {
my $R = $_;
...
}
Run Code Online (Sandbox Code Playgroud)
以下是另一种方法,但您可能应该避免,因为它的作用并不明显:
for my $R ( map $_, @CURR_RECS ) {
...
}
Run Code Online (Sandbox Code Playgroud)
您也可以避免复印。
my $R2 = join "|", split /\^/, $R, $KEY_POS+1;
print __LINE__ . ") ___ $R2";
Run Code Online (Sandbox Code Playgroud)
当然也比多次替换要快。