在字符串中搜索/替换

时间:2016-09-02 13:20:55

标签: regex perl search replace

我有一个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

我想知道这个问题是否有更好的方法?

2 个答案:

答案 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