假设我有两种类型的字符串:
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'。然后,我希望它在与第一个模式匹配时停止。似乎并非如此。我错过了什么?
请您参考如下方法:
根据文档,
As the target string is scanned, REs separated by '|' are tried from left to right. When one pattern completely matches, that branch is accepted. This means that once A matches, B will not be tested further, even if it would produce a longer overall match. In other words, the '|' operator is never greedy.
但行为似乎有所不同:
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 匹配 'Foobar',混合模式会得到那个 'Foobar' 并停止搜索。 (根据文档)
因为它没有像文档那样工作,所以解决方案必须依赖于 Python 的 或 短路:
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'>
