2010-10-28 35 views
1

我想在一個字符串,即在Java術語做兩個正則表達式替換用兩條正則表達式中的一個通

myString.replaceAll(pattern1, replacement1).replaceAll(pattern2, replacement2); 

然而,假設myString可能會很長,所以這將是希望避免做兩通過它。這可以一次完成嗎?

String pattern = ...; 
String replacement = ...; 
myString.replaceAll(pattern, replacement); 

pattern明顯的候選人是pattern1 + "|" + pattern2,但我看不出怎麼寫replacement

爲了簡化,我們假設的pattern1pattern2比賽不能相交,而replacement1不引入任何新的pattern2匹配。

+5

正在做兩遍更換_actually_性能問題?這聽起來像是對我不成熟的優化。 – 2010-10-28 18:09:05

+0

這更多的是我認爲很有趣的問題。我的情況很簡單,1)我可以避免它; 2)反正它不會是一個主要問題。 – 2010-10-28 18:26:22

+0

只因爲你*可以*做到這並不意味着這是一個好主意。您可能會在不需要的地方增加複雜性。 – 2010-10-28 20:26:58

回答

1

最簡單的方法是維護一個將字符串映射到替換項的散列。撰寫匹配任何鍵的匹配項,並將匹配的鍵傳遞給替換部分。有更換部分比拉值。

在Perl,這將僅僅是:

my @keys = keys %hash; 
my $alt = '\b(' . join("|", @keys) . ')\b'; 
s/($alt)/$hash{$1}/g; 

相應的Java的解決辦法 - 像一切 - 是顯著長,但同樣的方法是有效的。

如果一個字符串是另一個字符串的起始子字符串,則會出現排序問題。

1

根據您使用哪種編程語言的實際情況,您可以使用回調作爲替換,並使用與兩個事件匹配的RegExp,然後在回調函數中使用if語句來檢查匹配的正則表達式,用適當的替換替換它。

+0

已投注,但在我的情況下不可用。 – 2010-10-28 18:23:49

0

正如@levu所說,它取決於編程語言。在Ruby中,你可以做這樣的事情:

ree-1.8.7-2010.02 > s 
=> "hello world" 
ree-1.8.7-2010.02 > s.gsub(/(hello|world)/) {|match| match == 'hello' ? 'hi there!' : 'universe!' } 
=> "hi there! universe!" 

當GSUB看到無論是「你好」或「世界」字符串s時,將該值給塊變量稱爲匹配。該塊用「hi there!」替換「hello」,並用「universe!」替換任何其他值。

1

與其他幾乎所有的正則表達式不同,Java不支持回調。但是,它確實公開了一些允許您自己實現它們的較低級別的API調用。這裏說明了如何做一個帖子:

Java Regex Replace with Capturing Group

正如你所指出的,你需要的圖案合併爲一個,但你也需要每個圖案在自己的捕獲組隔離開來,就像這樣:

String bigPattern = "(" + pattern1 + ")|(" + pattern2 + ")"; 

(如果圖案已經包含捕獲組,這將改變編號方案,你必須調整任何反向引用我假設有,除了您剛纔創建的那些沒有捕獲組。)

然後,replacement()方法中,你確定這組居然匹配,並據此選擇替換文本:

public String replacement() 
{ 
    if (group(1) != null) 
    { 
    return replacement1; 
    } 
    else if (group(2) != null) 
    { 
    return replacement2; 
    } 
}