在Perl中,'在替换迭代器中使用未初始化的值' $ 1变量的错误

时间:2016-04-12 17:02:46

标签: regex perl

stackoverflow.com上的其他地方找到一个示例我试图在Perl中的字符串上的正则表达式匹配的第N个实例上替换。我的代码如下:

#!/usr/bin/env perl
use strict;
use warnings;

my $num_args = $#ARGV +1;
if($num_args != 3) {
        print "\nUsage: replace_integer.pl occurance replacement to_replace";
        print "\nE.g. `./replace_integer.pl 1 \"INTEGER_PLACEHOLDER\" \"method(0 , 1, 6);\"`";
        print "\nWould output: \"method(INTEGER_PLACEMENT , 1, 6);\"\n";
        exit;
}

my $string =$ARGV[2];

my $cont =0;
sub replacen { 
        my ($index,$original,$replacement) = @_;
        $cont++;
        return $cont == $index ? $replacement: $original;
}

sub replace_quoted {
        my ($string, $index,$replacement) = @_;
        $cont = 0; # initialize match counter
        $string =~ s/[0-9]+/replacen($index,$1,$replacement)/eg;
        return $string;
}

my $result = replace_quoted ( $string, $ARGV[0] ,$ARGV[1]);
print "RESULT: $result\n";

对于

./replace_integer.pl 3 "INTEGER_PLACEHOLDER" "method(0, 1 ,6);"

我希望输出

RESULT: method(0, 1 ,INTEGER_PLACEHOLDER);

不幸的是我得到了

的输出
RESULT: method(,  ,INTEGER_PLACEHOLDER);

有这些警告/错误

Use of uninitialized value in substitution iterator at ./replace_integer.pl line 26.
Use of uninitialized value in substitution iterator at ./replace_integer.pl line 26.

第26行是以下一行:

$string =~ s/[0-9]+/replacen($index,$1,$replacement)/eg;

我已经确定这是因为$ 1未初始化。据我所知,$ 1应该具有最后一场比赛的价值。鉴于我非常简单的正则表达式([0-9]+),我认为没有理由说它应该是未初始化的。

我知道有更简单的方法来查找和替换sed中的第N个实例,但是一旦克服了这个障碍,我将需要Perl的反向和前向引用(不支持sed)

是否有人知道此错误的原因以及如何解决此问题?

我正在使用Perl v5.18.2,专为x86_64-linux-gnu-thread-multi

而构建

感谢您的时间。

2 个答案:

答案 0 :(得分:1)

仅在捕获模式后才设置

$ 1,例如:

$foo =~ /([0-9]+)/;
# $1 equals whatever was matched between the parens above

尝试将匹配的parens包装为$ 1

答案 1 :(得分:1)

我会像这样写

while循环迭代字符串中\d+模式的出现次数。找到第N个匹配项后,使用内置数组substr(最后一个匹配的开头)和@-(结束时)中的值调用@+来替换最后一个匹配项最后一场比赛)

#!/usr/bin/env perl

use strict;
use warnings;

@ARGV = ( 3, 'INTEGER_PLACEHOLDER', 'method(0, 1, 6);' );

if ( @ARGV != 3 ) {
    print qq{\nUsage: replace_integer.pl occurrence replacement to_replace};
    print qq{\nE.g. `./replace_integer.pl 1 "INTEGER_PLACEHOLDER" "method(0 , 1, 6);"`};
    print qq{\nWould output: "method(INTEGER_PLACEMENT , 1, 6);"\n};
    exit;
}

my ( $occurrence, $replacement, $string ) = @ARGV;

my $n;
while ( $string =~ /\d+/g ) {

    next unless ++$n == $occurrence;

    substr $string, $-[0], $+[0]-$-[0], $replacement;
    last;
}

print "RESULT: $string\n";

输出

$ replace_integer.pl 3 INTEGER_PLACEHOLDER 'method(0, 1, 6);'
RESULT: method(0, 1, INTEGER_PLACEHOLDER);

$ replace_integer.pl 2 INTEGER_PLACEHOLDER 'method(0, 1, 6);'
RESULT: method(0, INTEGER_PLACEHOLDER, 6);

$ replace_integer.pl 1 INTEGER_PLACEHOLDER 'method(0, 1, 6);'
RESULT: method(INTEGER_PLACEHOLDER, 1, 6);