使用qr //将RegEx替换为子例程

时间:2017-01-29 20:46:14

标签: perl

我有一个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//来传递替换正则表达式并获得相同的结果。

2 个答案:

答案 0 :(得分:3)

首先,使用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');

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

if ($args[0] instanceof ActiveRecordField) // False

if ($args[0] instanceof \MyCompany\Classes\ActiveRecordField) // True

答案 1 :(得分:1)

你必须明白,替换中的文本不是正则表达式,而是一个准备插入的字符串。因此,您必须执行诸如解决方法之类的操作,以便延迟插值,直到正则表达式针对所需的字符串运行。

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