使用 qr// 将替换正则表达式传递到子例程



我有一个find_replace子例程,它接受参数(内容,查找正则表达式,替换正则表达式,用于存储结果的结果变量)。我使用 qr// 来传递查找和替换正则表达式。查找正则表达式效果很好,但替换正则表达式则不然。

$text = "11 22 33 44 55";
find_replace($text,qr/(33 )(.*?)( 55)/,qr/$1<BOLD>$2</BOLD>$3/,my $newText);
print $newText;
     #Should print: 11 22 <I>33 <B>44</B> 55</I>
     #But it prints: 11 22 <I>(?^:<B></B>)</I>
sub find_replace {
    my $content = shift;
    my $findRegEx = shift;
    my $replaceRegEx = shift;
    my $newVariable = shift;
    ${$newVariable} = $content;
    ${$newVariable} =~ s/$findRegEx/<I>$replaceRegEx</I>/g;
}

我已经找到了解决此问题的方法:

$text = "11 22 33 44 55";
find_replace($text,qr/(33 )(.*?)( 55)/,sub{"$1<B>$2</B>$3"},my $newText);
print $newText;
     #Prints: 11 22 <I>33 <B>44</B> 55</I>
sub find_replace {
    my $content = shift;
    my $findRegEx = shift;
    my $replaceRegEx = shift;
    my $newVariable = shift;
    ${$newVariable} = $content;
    ${$newVariable} =~ s($findRegEx){ "<I>".$replaceRegEx->()."</I>" }ge;
}

但是此修复程序使用sub{"…"}而不是qr/…/。我正在寻找的是继续使用 qr// 来传递替换正则表达式并获得相同的结果。

首先,使用 qr// 作为替换表达式是没有意义的,因为替换表达式不是正则表达式模式。 qq//(双引号字符串)和q//(单引号字符串)用于构造字符串。

主要问题是

s/$findRegEx/<I>$replaceRegEx</I>/g

方法

my $repl_expr = sub { qq/<I>$replaceRegEx</I>/ };  # Interpolates $replaceRegEx
s/$findRegEx/ $repl_expr->() /eg

但你真的想要

my $repl_expr = sub { qq/$1<B>$2</B>$3/ };         # Interpolates $1, $2 and $3
s/$findRegEx/ $repl_expr->() /eg

如果您需要从字符串开始(例如,替换表达式来自配置文件),那么您可以通过以下方法实现您想要的:

use String::Substitution qw( gsub_copy );
my $newText = gsub_copy($text, qr/(33 )(.*?)( 55)/, '$1<BOLD>$2</BOLD>$3');

您必须了解替换中的文本不是正则表达式,而是一个字符串,随时可以插入。 因此,您必须执行诸如解决方法之类的操作,以便延迟内插,直到正则表达式针对所需的字符串运行为止。

话虽如此,如果你的 sub 就这么简单,我不确定你是否真的应该把它放在 sub 中 - s运算符已经是一个 sub 调用,你只是让事情复杂化。 当然,在某些情况下,您需要将正则表达式或其他任何东西传递给更复杂的子,这可能是一件好事,但您仍然需要这种类型的延迟插值才能使其工作。

最新更新