将几个正则表达式合并为一个RE

时间:2011-07-07 16:22:35

标签: python regex

我已经编写了两个RE来匹配String中的几个字符串序列。例如假设两个正则表达式为RE1RE2。字符串可以是这4种形式;

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检查这些内容,但我知道它非常昂贵,因为我正在多次匹配特定字符串。我想过使用'或'|,但问题是regex会在找到第一个匹配序列后停止匹配,而不是继续查找其他序列。我想一次或多次找到匹配的序列。

更新

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'

如何合并这两个RE以使我的程序高效。我正在使用python来编写代码。

5 个答案:

答案 0 :(得分:6)

你说“我知道它非常昂贵,因为我正在为特定字符串进行多次匹配。”这告诉我你几次运行每个RE。在这种情况下,你犯了一个错误,可以在不编写更复杂的RE的情况下解决。

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

这将产生两个匹配列表。然后,您可以对这些列表执行布尔运算,以生成所需的任何结果;或者如果你需要一个列表中的所有匹配项,你可以连接它们。如果您不需要结果列表,您还可以使用re.match(匹配锚定在字符串的开头)或re.search(匹配字符串中的任何位置),但只需要知道有一场比赛。

在任何情况下,在这种情况下创建更复杂的RE可能不是必需的或不可取的。

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


有关如何使用布尔运算符处理列表的一些建议。首先是一些设置:

>>> 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)
如果所有结果都为True,

and将返回第一个False结果或最终结果。

>>> not re1_matches and re2_matches
False

因此,如果你想要列表而不是平面布尔值,你必须测试你想要的结果:

>>> 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']

答案 1 :(得分:6)

你需要在第二个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])

答案 2 :(得分:2)

  

我想过使用'或'|,但问题是regex会在找到第一个匹配序列后停止匹配而不会继续找到其他匹配序列。

这就是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', '')]

答案 3 :(得分:1)

在你的正则表达式和re.findall()中使用|可能是要走的路,这是一个例子:

>>> 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']

如果您的模式重叠有效,那么这将无效。

答案 4 :(得分:0)

如果RE1和RE2可以匹配字符串的相同字符,请单独检查它们(RE1是否与字符串匹配,RE2是否与字符串匹配)。