我有一个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 调用,你只是让事情复杂化。 当然,在某些情况下,您需要将正则表达式或其他任何东西传递给更复杂的子,这可能是一件好事,但您仍然需要这种类型的延迟插值才能使其工作。