2015-11-11 49 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/; 
}