如何做条件(“如果存在”逻辑)搜索&在Perl中替换?

时间:2016-02-17 08:57:10

标签: regex perl search replace conditional

在我的Perl脚本中我想做条件搜索&使用正则表达式替换:查找某个模式,如果模式存在于哈希中,则将其替换为其他模式。

例如,我想搜索“pattern1”和“pattern2”的组合,如果后者存在于散列中,则将组合替换为“pattern1”和“replacement”。我尝试了以下内容,但它根本没有做任何事情。

$_ =~ s/(pattern1)(pattern2)/$1replacement/gs if exists $my_hash{$2};

我也试过像这样的东西:

$_ =~ s/(pattern1)(pattern2) && exists $my_hash{$2}/$1replacement/gs;

也什么都不做,好像没有找到匹配。

任何人都可以帮我解决这个正则表达式问题吗? THX〜

2 个答案:

答案 0 :(得分:2)

我会以不同的方式做到这一点。看起来你有一个搜索它,取而代之的是'哈希值。

所以:

#!/usr/bin/env perl
use strict;
use warnings;

#our 'mappings'. 
#note - there can be gotchas here with substrings
#so make sure you anchor patterns or sort, so 
#you get the right 'substring' match occuring. 

my %replace = (
    "this phrase" => "that thing",
    "cabbage"     => "carrot"
);

#stick the keys together into an alternation regex. 
#quotemeta means regex special characters will be escaped. 
#you can remove that, if you want to use regex in your replace keys.     
my $search = join( "|", map {quotemeta} keys %replace );
#compile it - note \b is a zero width 'word break' 
#so it will only match whole words, not substrings. 
$search = qr/\b($search)\b/;

#iterate the special DATA filehandle - for illustration and a runnable example. 
#you probably want <> instead for 'real world' use. 
while (<DATA>) {
    #apply regex match and replace
    s/(XX) ($search)/$1 $replace{$2}/g;
    #print current line. 
    print;
}

##inlined data filehandle for testing. 
__DATA__
XX this phrase cabbage
XX cabbage carrot cabbage this phrase XX this phrase
XX no words here
and this shouldn't cabbage match this phrase at all

通过这样做,我们将您的哈希键转换为正则表达式(您可以打印它 - 看起来像:(?^:\b(cabbage|this\ phrase)\b)

将其插入替换模式中。如果密钥存在,这将匹配,因此您可以安全地执行替换操作。

注意 - 我添加了quotemeta,因为它会转义密钥中的任何特殊字符。而\b是一个&#34;字边界&#34;匹配所以它不会在单词中进行子串。 (显然,如果你想要那个,那就去除它们)

以上给出了输出:

XX that thing cabbage
XX carrot carrot cabbage this phrase XX that thing
XX no words here
and this shouldn't cabbage match this phrase at all

如果你想省略没有模式匹配的行,你可以在正则表达式之后粘贴&& print;

答案 1 :(得分:1)

有什么问题(如不工作)
if (exists($h{$patt1)) { $text =~ s/$patt1$patt2/$patt1$1replacement/g; }

如果$patt1作为哈希中的键存在,那么您可以继续将$patt1$patt2替换为$patt1$replacement。当然,如果在$patt1$patt2中找到$text,则不会发生任何事情。您的第一个代码段是循环的,而第二个代码片段根本无法正常工作。

如果您首先需要$patt1$patt2哈希密钥,那么您似乎必须放慢速度

if ($str =~ /$patt11$patt2/ && exists $h{$patt2}) {
     $str =~ s/$patt1$patt2/$patt1$replacement/gs;
}

如果这是你想要的,那么它很简单:你需要两个不相关的条件,无论你转向它的方式。无法合并它们,因为它是圆形的。

从结果来看,这些都是一样的。如果任何一种情况失败,无论您检查它们的顺序如何,都不会发生任何事情。

注意或者您可能不会放慢速度,请参阅Sobrique的帖子。