一些正則表達式引擎(例如PCRE)具有構造(?|...)
。它就像一個非捕獲組,但具有很好的特性,即在每個交替組中都從相同的初始值開始計數。這可能會立即解決您的問題。所以如果切換語言這個任務是你的選擇,那應該可以做到。
[編輯:事實上,它仍然會引起衝突命名爲捕獲組的問題。實際上,該模式甚至不會編譯,因爲組名不能被重用。]
否則,您將不得不操縱輸入模式。海德建議重新編號反向引用,但我認爲有一個更簡單的選項:使所有組命名爲組。你可以向你保證這些名字是獨一無二的。
因此,基本上,對於每個輸入模式,您創建一個唯一的標識符(例如,增加一個ID)。然後最棘手的部分是在模式中找到捕獲組。你將無法用正則表達式來做到這一點。你將不得不自己解析模式。如果您只是遍歷模式字符串,請注意以下幾點:
- 請注意當您進入和離開字符類時,因爲字符類內部括號是文字字符。
- 也許最棘手的部分:忽略後跟
?:
,?=
,?!
,?<=
,?<!
,?>
所有打開的括號。此外,還有選項設置圓括號:(?idmsuxU-idmsuxU)
或(?idmsux-idmsux:somePatternHere)
,它們也不會捕獲任何內容(當然,這些選項可能有任何子集,它們可以以任意順序排列 - -
也是可選的)。
- 現在你應該只剩下開放的圓括號,這個圓括號既可以是正常的捕獲組,也可以是:
(?<name>
。最簡單的事情可能是把它們都一視同仁 - 也就是擁有一個數字和一個名字(如果它沒有設置,名字就等於數字)。然後你用(?<uniqueIdentifier-md5hashOfName>
這樣的東西重寫所有這些(連字符實際上不是名稱的一部分,你只需要你遞增的數字後面跟着散列 - 因爲散列是固定長度的,不會有任何重複;非常多至少)。確保記住該組最初有哪些號碼和名稱。
- 每當遇到反斜槓時,有三個選項:
- 下一個字符是一個數字。你有一個編號的反向引用。將所有這些數字替換爲
k<name>
,其中name
是您爲該組生成的新組名稱。
- 接下來的字符是
k<...>
。再次將其替換爲相應的新名稱。
- 下一個字符是別的。跳過它。它同時處理括號轉義和反斜槓轉義。
- 我認爲Java可能允許前向引用。在這種情況下,你需要兩次傳球。照顧重新命名所有組。然後更改所有參考。
一旦你在每個輸入模式上完成了這一步,就可以安全地將它們全部與|
合併。除反向引用以外的任何其他功能都不會導致此方法出現問題。至少不會只要你的模式有效。當然,如果你有輸入a(b
和c)d
那麼你有問題。但是,如果你不檢查模式是否可以自行編譯,你會一直這樣做。
我希望這給你一個正確的方向指針。
一個正則表達式匹配字符串的一部分還是匹配整個字符串? – Tomalak
@Tomalak由用戶提供的正則表達式應該被允許匹配(2)中的部分字符串 - 特別是在我使用Matcher.find()的天真實現中,看看是否至少有匹配 – CAFxX
讓你認爲'regex1 | regex2 | regex3'產生錯誤的結果?你能構建一個它會的情況嗎? – Tomalak