如何替换 Perl 正则表达式中第 n 次出现的匹配项?

Zai*_*aid 5 regex perl substitution

继之前关于提取第 n 个正则表达式匹配的问题之后,我现在需要替换该匹配(如果找到)。

\n\n

我认为我可以定义提取子例程并在带有修饰符的替换中调用它/e。我显然错了(诚然,我有一个XY 问题)。

\n\n
use strict;\nuse warnings;\n\nsub extract_quoted { # \xc3\xa0 la codaddict\n\n        my ($string, $index) = @_;\n        while($string =~ /\'(.*?)\'/g) {\n                $index--;\n                return $1 if(! $index);\n        }\n        return;\n}\n\nmy $string = "\'How can I\',\'use\' \'PERL\',\'to process this\' \'line\'";\n\nextract_quoted ( $string, 3 );\n$string =~ s/&extract_quoted($string,2)/\'Perl\'/e;\n\nprint $string; # Prints \'How can I\',\'use\' \'PERL\',\'to process this\' \'line\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

当然,这种技术还存在许多其他问题:

\n\n
    \n
  • 如果不同位置有相同的匹配怎么办?
  • \n
  • 如果没有找到匹配怎么办?
  • \n
\n\n

鉴于这种情况,我想知道可以通过什么方式来实现。

\n

leo*_*loy 3

或者你可以这样做

use strict;
use warnings;

my $string = "'How can I','use' .... 'perl','to process this' 'line'";

my $cont =0;
sub replacen { # auxiliar function: replaces string if incremented counter equals $index
        my ($index,$original,$replacement) = @_;
        $cont++;
        return $cont == $index ? $replacement: $original;
}

#replace the $index n'th match (1-based counting) from $string by $rep
sub replace_quoted {
        my ($string, $index,$replacement) = @_;
        $cont = 0; # initialize match counter
        $string =~ s/'(.*?)'/replacen($index,$1,$replacement)/eg;
        return $string;
}

my $result = replace_quoted ( $string, 3 ,"PERL");
print "RESULT: $result\n";
Run Code Online (Sandbox Code Playgroud)

“全局”$cont 变量有点难看,可以改进,但你明白了。

更新:更紧凑的版本:

use strict;
my $string = "'How can I','use' .... 'perl','to process this' 'line'";

#replace the $index n'th match (1-based counting) from $string by $replacement
sub replace_quoted {
        my ($string, $index,$replacement) = @_;
        my $cont = 0; # initialize match counter
        $string =~ s/'(.*?)'/$cont++ == $index ? $replacement : $1/eg;
        return $string;
}

my $result = replace_quoted ( $string, 3 ,"PERL");
print "RESULT: $result\n";
Run Code Online (Sandbox Code Playgroud)