我有一个Perl程序,用户可以在其中输入一些文本,搜索模式和替换字符串。
我使用s///
运算符用替换字符串替换搜索模式,但在这种情况下,如果用户输入捕获变量(如$1
)或反斜杠转义符(如{{在替换字符串中,替换模式应该处理这些元字符,而是将它们视为字符串字符。
我有以下代码:
\u
此代码的示例输入为
\L
以上代码的输出是
#!/usr/bin/perl -w
use strict;
chomp(my $text = <STDIN>); #read the text
chomp(my $regex = <STDIN>); #read the search pattern
chomp(my $replace = <STDIN>); #read the replacement pattern
$text=~s/$regex/$replace/g; # do replacement
print $text,"\n";
我在以下代码中找到了一种方法:
fred flintstone and wilma flintstone are good couples
(fred|wilma) flintstone
\u\L$1\E Flintstone
现在这段代码给出了正确的输出
\u\L$1\E Flintstone and \u\L$1\E Flintstone are good couples
我想知道这个问题是否有更好的方法?
答案 0 :(得分:4)
如果没有编译,则无法插入双引号字符串
/ee
修饰符带有与eval
相同的警告:执行用户输入的任何类型的代码总是很危险的,甚至一个简单的字符串也可能包含一个由任何Perl代码组成的块用户喜欢输入,例如"my dangerous string @{ unlink glob '*.*'}"
我建议您使用优秀的String::Interpolate
模块,该模块会导出safe_interpolate
函数,该函数将使用Safe
模块在“安全”隔间中执行插值
#!/usr/bin/perl
use strict;
use warnings 'all';
use String::Interpolate 'safe_interpolate';
my $text = 'fred flintstone and wilma flintstone are good couples';
my $regex = '(fred|wilma) flintstone';
my $replace = '\u\L$1\E Flintstone';
$text =~ s/$regex/ safe_interpolate($replace) /eg; # do replacement
print $text,"\n";
答案 1 :(得分:4)
(首先,你不应该再使用-w
。它在2000年被(词法范围的,更可预测的)use warnings
pragma取代了。)
对于您的问题,您可以使用replace
模块中的Data::Munge,这是&#34; javascript&#39; s String.prototype.replace
&#34;的克隆。
use Data::Munge qw(replace);
$text = replace($text, $regex, $replace, 'g');
这会扩展$&
或$1
之类的内容,但不会扩展反斜杠序列,例如\u
。为此,您可以指定自己的扩展功能,但是您必须手动解析并替换替换字符串中的特殊序列。对于$1
和朋友来说,这很简单,但像\Ufoo\Q$1\Ebar\Ebaz
这样的内容很难正确处理,尤其是$1
包含'\E'
时(即使perl本身在此方面存在问题)历史)。但如果你让那部分工作,那么很容易插入replace
。