Skip to main content
 首页 » 编程设计

带有 or 和 re.search 的 Python 正则表达式

2025年04月02日29Renyi-Fan

假设我有两种类型的字符串:

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