Perl同时替换多个字符串(不区分大小写)

时间:2014-12-09 00:19:14

标签: perl

考虑以下完美运行的perl代码:

%replacements = ("what" => "its", "lovely" => "bad");
($val = $sentence) =~ s/(@{[join "|", keys %replacements]})/$replacements{$1}/g;

stackoverflow用户sresevoir出色地提出了使用哈希的替换代码,允许您查找和替换多个术语而无需迭代循环。

我已经以编程方式投放其他各种搜索和替换字词,并且我已开始使用它来突出显示搜索结果的字词。

问题(参见下面显示的问题代码):

通过添加" i"使其不区分大小写。在" g"之前在末尾。 如果搜索词$ thisterm和$ sentence中包含的搜索词词在大小写上没有区别,则没有问题。如果搜索项$ thisterm(即Stackoverflow)和$ sentence中包含的搜索项词是不同的情况(即stackoverflow),则返回的结果对于该术语不是任何内容。好像我告诉它

$sentence =~ s/$thisterm//g;

这是问题代码:

foreach $thisterm (@searchtermarray) {

# The variable $thisterm has already gone through a filter to remove special characters.

$thistermtochange = $thisterm;

$replacements{$thistermtochange} = "<span style=\"background-color:#FFFFCC;\">$thistermtochange<\/span>";

}

$sentence =~ s/(@{[join "|", keys %replacements]})/$replacements{$1}/ig;

我还回过头来用上面的原始代码重复了这个问题。似乎添加i修饰符,使用哈希引用和不同情况的组合是Perl不喜欢的。

我错过了什么?

谢谢,

DB

P上。 S.我多年来从stackoverflow中受益;但我刚刚注册了这个问题,该网站不会让我直接评论sresevoir。作为一个全新的&#34;用户我没有足够的声誉点。

2 个答案:

答案 0 :(得分:1)

将散列的所有键保持为小写,并执行以下操作:

s/(@{[join "|", keys %replacements]})/$replacements{ lc $1 }/ig

(注意增加lc)

还有一些其他事情你应该考虑。

首先,如果您尝试使用不同的替换替换lovelylove,则可能会找到lovely,也可能找不到keys,具体取决于返回的是哪个键s/(@{[join "|", sort { length $b <=> length $a } keys %replacements]})/$replacements{$1}/ig 首先。为了防止这种情况,按降序排序是个好主意:

how?

其次,这种技术仅适用于固定字符串;如果您的密钥包含任何正则表达式元字符,例如将why?替换为$1,则会失败,因为how?永远不会是s/(@{[join "|", map quotemeta, sort { length $b <=> length $a } keys %replacements]})/$replacements{$1}/ig 。要允许元字符(解释为文字字符),请引用它们:

 s/(@{[join "|", map quotemeta, sort { length $b <=> length $a } @search_strings]})/<span style="background-color:#FFFFCC;">$1<\/span>/ig;

从你的评论中,我觉得你想要在一次通过中找到某些字符串,并在它们周围添加东西(不会因字符串而异)。如果是这样,那么你就是在艰难的道路上进行,并且根本不应该使用哈希。有一个你想要搜索的字符串数组并替换它们:

{{1}}

答案 1 :(得分:0)

问题是,如果你有像这样的哈希

my %replacements = (
    word => '<span style="background-color:#FFFFCC;">word</span>'
)

然后替换将看起来像

s/(word)/$replacements{$1}/ig;

但是,与案例无关的正则表达式模式也会与WORD匹配,因此替换表达式$replacements{$1}将为$replacements{'WORD'},但不存在。

虽然您可能对他的解决方案感到满意,但sresevoir使用了一种在正则表达式中嵌入字符串表达式的丑陋方式。此

($val = $sentence) =~ s/(@{[join "|", keys %replacements]})/$replacements{$1}/g;

会好得多。

my $pattern = join '|', keys %replacements;
($val = $sentence) =~ s/($pattern)/$replacements{$1}/g;

但是你已经把这个哈希想法推广得太过分了,而且你做出你需要的改变是错误的。如果替换字符串是原始字符串的简单函数(如本例所示),则最好使用模式中的捕获将其直接写为替换字符串。我会这样写的

my $pattern = join '|', @searchtermarray;
$sentence =~ s{($pattern)}{<span style="background-color:#FFFFCC;">$1</span>\n}ig;

但请注意,就目前情况而言,搜索会在文本中找到任何子串的字词,如果@searchtermarray包含任何字符串,也会出错正则表达式元字符。你没有说出你的实际数据,所以我无法真正帮助你解决这个问题。