簡體   English   中英

將多個正則表達式合並為一個 RE

[英]Merge several regular expressions into one RE

我寫了 2 個 RE 來匹配一個字符串中的幾個字符串序列。 例如,假設兩個正則表達式是RE1RE2 字符串可以在這4個forms中;

1) Match ONLY RE1 'one or more times'
2) Match ONLY RE2 'one or more times'
3) Match RE1 'one or more times' AND match RE2 'one or more times'
4) Match NEITHER RE1 NOR RE2 

目前我正在使用if來檢查其中的每一個,但我知道它非常昂貴,因為我正在多次匹配特定字符串。 我想用'或' | 但問題是正則表達式一旦找到第一個匹配序列就會停止匹配,而不是繼續找到其他序列。 我想“一次或多次”找到匹配的序列。

更新:

eg: RE1 = (\d{1,3}[a-zA-Z]?/\d{1,3}[a-zA-Z]?)
    RE2 = (\babc\b)
String: *some string* 100/64h *some string* 120h/90 *some string* abc 200/100 abc *some string* 100h/100f

Matches: '100/64h', '120h/90', 'abc', '200/100', 'abc', '100h/100f'

如何合並這 2 個 RE 以使我的程序高效。 我正在使用 python 對此進行編碼。

您說“我知道它非常昂貴,因為我要多次匹配特定字符串。” 這對我來說意味着您要多次運行每個 RE。 在這種情況下,您犯了一個無需編寫更復雜的 RE 即可解決的錯誤。

re1_matches = re.findall(re1, text)
re2_matches = re.findall(re2, text)

這將產生兩個匹配列表。 然后,您可以對這些列表執行 boolean 操作以生成您需要的任何結果; 或者,如果您需要一個列表中的所有匹配項,則可以將它們連接起來。 如果您不需要結果列表,您也可以使用re.match (匹配在字符串開頭的匹配)或re.search (匹配字符串中的任何位置),但只需要知道有一個匹配項。

在任何情況下,在這種情況下創建更復雜的 RE 可能是不必要或不可取的。

但是我並不清楚你到底想要什么,所以我可能錯了。


關於如何使用 boolean 運算符處理列表的一些建議。 首先一些設置:

>>> re1 = r'(\d{1,3}[a-zA-Z]?/\d{1,3}[a-zA-Z]?)'
>>> re2 = r'(\babc\b)'
>>> re.findall(re1, text)
['100/64h', '120h/90', '200/100', '100h/100f']
>>> re.findall(re2, text)
['abc', 'abc']
>>> re1_matches = re.findall(re1, text)
>>> re2_matches = re.findall(re2, text)
>>> rex_nomatch = re.findall('conglomeration_of_sandwiches', text)

如果所有結果都為真and則返回第一個 False 結果或最終結果。

>>> not re1_matches and re2_matches
False

因此,如果您想要列表而不是平坦的 boolean,則必須測試最后想要的結果:

>>> not rex_nomatch and re1_matches
['100/64h', '120h/90', '200/100', '100h/100f']

相似地:

>>> not rex_nomatch and re2_matches
['abc', 'abc']

如果您只想知道兩個 RE 都生成了匹配項,但不再需要,您可以這樣做:

>>> re1_matches and re2_matches
['abc', 'abc']

最后,如果兩個 RE 都生成匹配項,這是一種獲得連接的緊湊方法:

>>> re1_matches and re2_matches and re1_matches + re2_matches
['100/64h', '120h/90', '200/100', '100h/100f', 'abc', 'abc']

您需要在第二個 RE 中轉義 \:

RE1 = '(\d{1,3}[a-zA-Z]?/\d{1,3}[a-zA-Z]?)'
RE2 = '(\\babc\\b)'
s = '*some string* 100/64h *some string* 120h/90 *some string* abc 200/100 abc *some string* 100h/100f'


p = re.compile('('+RE2+'|'+RE1+')');
matches = p.findall(s)

for match in matches:
    print(match[0])

我想用'或' | 但問題是正則表達式一旦找到第一個匹配序列就會停止匹配,而不是繼續找到其他序列。

這就是re.findall的用途。

>>> import re
>>> RE = r'(?:\d{1,3}[a-zA-Z]?/\d{1,3}[a-zA-Z]?)|(?:\babc\b)'
>>> string = '*some string* 100/64h *some string* 120h/90 *some string* abc 200/100 abc *some string* 100h/100f'
>>> re.findall(RE, string)
['100/64h', '120h/90', 'abc', '200/100', 'abc', '100h/100f']

注意非捕獲括號的使用( (?:...)東西)。 如果正則表達式正常使用捕獲分組括號, re.findall將返回[('100/64h', ''), ('120h/90', ''), ('', 'abc'), ('200/100', ''), ('', 'abc'), ('100h/100f', '')]

使用| 在你的正則表達式和re.findall()可能是 go 的方式,這是一個例子:

>>> pattern = re.compile(r"(\d{1,3}[a-zA-Z]?/\d{1,3}[a-zA-Z]?|\babc\b)")
>>> pattern.findall("*some string* 100/64h *some string* 120h/90 *some string* abc 200/100 abc *some string* 100h/100f")
['100/64h', '120h/90', 'abc', '200/100', 'abc', '100h/100f']

如果您的模式重疊是有效的,那么這將不起作用。

如果 RE1 和 RE2 可以匹配字符串的相同字符,則分別檢查它們(RE1 是否匹配字符串,RE2 是否匹配字符串)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM