2015-11-11 48 views
0

我正在研究perl中的程序,并且试图在绑定运算符中结合多个正则表达式。我曾尝试使用下面的语法,但它不起作用。我想知道是否还有其他方法可以解决这个问题。在perl中使用绑定运算符

$in =~ (s/pattern/replacement/)||(s/pattern/replacement/)||... 
+1

您能提供一些预期行为的例子吗?此外,您可以在正则表达式中使用'|'作为“或”。 – Arc676

+0

使用上面的语法只是第一次替换,我也尝试过使用其他运算符 – Kev

+0

用'or'分隔的表达式链将在其中一个表达式返回真值时始终停止。这就是布尔运算符被描述为“短路”时的意思。 –

回答

2

你可以经常得到关于Perl的使得使用B::Deparse一些代码有什么线索。

$ perl -MO=Deparse -E'$in =~ (s/pattern1/replacement1/)||(s/pattern2/replacement2/)' 
[ ... snip ... ] 
s/pattern2/replacement2/u unless $in =~ s/pattern1/replacement1/u; 
-e syntax OK 

因此它试图在$in上进行第一次替换。如果失败了,那么它会尝试你的第二次替代。但是它不使用$in进行第二次替换,而是使用$_代替。

您正遇到优先问题。 Perl会将您的代码解释为:

($in =~ s/pattern1/replacement1/) or (s/pattern2/replacement2/) 

请注意,左括号已在$in之前移动。

正如其他人指出的那样,最好在这里使用循环方法。但我认为解释为什么你的版本不起作用可能很有用。

更新:要清楚,如果你想使用的语法这样,那么你将需要:

($in =~ s/pattern1/replacement1/) or 
($in =~ s/pattern2/replacement2/); 

请注意,我包括在每个表达$in =~。在这一点上,它变得明显(我希望)为什么循环解决方案更好。

但是,由于or是短路运算符,因此该语句将在第一次成功替换后停止。我认为这就是你在原始代码中使用它的原因。如果这不是你想要的,那么你需要切换到使用and或者(更好,在我看来)将它们分解成单独的语句。

$in =~ s/pattern1/replacement1/; 
$in =~ s/pattern2/replacement2/; 
+0

感谢您的帮助。我试着用括号来分隔每个替换,但它仍然只给出第一个替换。我理解你的观点,我非常感谢。 – Kev

+1

@Kev,重温Dave Cross写的。 '($ in =〜s/pattern1/replacement1 /)或(s/pattern2/replacement2 /)'不是解决方案;这是你写的东西的意思。 – ikegami

+0

已更新,使其(希望)更清晰。 –

1

更简单的方法可能是创建所有这些模式和替换的数组,然后简单地通过你的阵列迭代在次施加取代基的一种模式。

my $in = "some string you want to modify"; 
my @patterns = (
    ['pattern to match', 'replacement string'], 
    # ... 
); 

$in = replace_many($in, \@patterns); 

sub replace_many { 
    my ($in, $replacements) = @_; 

    foreach my $replacement (@$replacements) { 
     my ($pattern, $replace_string) = @$replacement; 

     $in =~ s/$pattern/$replace_string/; 
    } 

    return $in; 
} 
+0

@Kev您可以点击“接受”(复选标记)表示您已接受答案。 – Arc676

2

你可以得到的最接近的一个语法寻找类似于将

s/one/ONE/ or 
s/two/TWO/ or 
... 
s/ten/TEN/ for $str; 

这将尝试反过来每个取代,只有一次,第一次成功后,一个停止。

0

这并不完全清楚你需要什么,而且你完全不清楚你是否可以用你所建议的方式完成你看来想要的东西。 OR运算符是一个短路运算符,您可能不想要这种行为。请给出你期望的输入和你想要的输出的例子,希望每个例子都有。同时,这里是一个测试脚本。

use warnings; 
    use strict; 

    my $in1 = 'George Walker Bush'; 
    my $in2 = 'George Walker Bush'; 
    my $in3 = 'George Walker Bush'; 
    my $in4 = 'George Walker Bush'; 

    (my $out1 = $in1) =~ s/e/*/g; 
    print "out1 = $out1 \n"; 

    (my $out2 = $in2) =~ s/Bush/Obama/; 
    print "out2 = $out2 \n"; 

    (my $out3 = $in3) =~ s/(George)|(Bush)/Obama/g; 
    print "out3 = $out3\n"; 

    $in4 =~ /(George)|(Walker)|(Bush)/g; 
    print "$1 - $2 - $3\n"; 

    exit(0); 

您会注意到在最后一种情况下,只有第一个OR运算符在正则表达式中匹配。如果你想用巴拉克侯赛因奥巴马取代乔治沃克布什,那么你可以轻松地做到这一点,但你也可以用'巴拉克华盛顿'取代'乔治华盛顿' - 这就是你想要的吗?下面是脚本的输出:

out1 = G*org* Walk*r Bush 
out2 = George Walker Obama 
out3 = Obama Walker Obama 
Use of uninitialized value $2 in concatenation (.) or string at pq_151111a.plx line 19. 
Use of uninitialized value $3 in concatenation (.) or string at pq_151111a.plx line 19. 
George - - 
2

使用for为 “topicalize”(别名$_到您的变量)。

for ($in) { 
    s/pattern/replacement/; 
    s/pattern/replacement/; 
}