使用or和re.search的Python正则表达式

时间:2016-07-25 22:54:57

标签: python regex

说我有两种类型的字符串:

str1 = 'NUM-140 A Thing: Foobar Analysis NUM-140'
str2 = 'NUM-140 Foobar Analysis NUM-140'

对于这两个,我想匹配'Foobar'(可能是任何东西)。我尝试过以下方法:

m = re.compile('((?<=Thing: ).+(?= Analysis))|((?<=\d ).+(?= Analysis))')

ind1 = m.search(str1).span()
match1 = str1[ind1[0]:ind1[1]]

ind2 = m.search(str2).span()
match2 = str2[ind2[0]:ind2[1]]

然而,match1出现在'A Thing: Foobar',这似乎是第二种模式的匹配,而不是第一种模式。单独应用(模式1到str1和模式2到str2,没有|),两个模式都匹配'Foobar'。我预计这会在第一个模式匹配时停止。这似乎并非如此。我错过了什么?

2 个答案:

答案 0 :(得分:1)

根据文件,

  

扫描目标字符串时,RE由&#39; |&#39;分隔。从左到右尝试。当一个模式完全匹配时,接受该分支。这意味着一旦A匹配,B将不会被进一步测试,即使它会产生更长的整体匹配。换句话说,&#39; |&#39;操作员从不贪心。

但行为似乎有所不同:

import re

THING = r'(?<=Thing: )(?P<THING>.+)(?= Analysis)'
NUM = r'(?<=\d )(?P<NUM>.+)(?= Analysis)'
MIXED = THING + '|' + NUM

str1 = 'NUM-140 A Thing: Foobar Analysis NUM-140'
str2 = 'NUM-140 Foobar Analysis NUM-140'

print(re.match(THING, str1))
# <... match='Foobar'>
print(re.match(NUM, str1))
# <... match='A Thing: Foobar'>
print(re.match(MIXED, str1))
# <... match='A Thing: Foobar'>

我们希望因为THING匹配&#39; Foobar&#39;,MIXED模式将获得&#39; Foobar&#39;并退出搜索。 (根据文件)

因为它没有按照文档记录的方式工作,所以解决方案必须依赖于Python的or短路:

print(re.search(THING, str1) or re.search(NUM, str1))
# <_sre.SRE_Match object; span=(17, 23), match='Foobar'>

print(re.search(THING, str2) or re.search(NUM, str2))
# <_sre.SRE_Match object; span=(8, 14), match='Foobar'>

答案 1 :(得分:0)

如果您使用命名组,例如(?P<name>...),您将能够更轻松地进行调试。但请注意span的文档。

https://docs.python.org/2/library/re.html#re.MatchObject.span

  

span([group])对于MatchObject m,返回2元组(m.start(组),   m.end(组))。请注意,如果组没有参与比赛,   这是(-1,-1)。组默认为零,整个匹配。

你没有传递组号。

为什么你还在使用span?只需使用m.search(str1).groups()或类似的

即可