给出字符串1:
''' TOM 喜欢去游泳 玛丽 喜欢去操场 JANE 喜欢去购物''
我想在两个名字之间捕捉文字。无论是汤姆和玛丽还是汤姆和简。如果玛丽出现在简之前,我想捕捉汤姆和玛丽之间的文字。但是,如果Jane首先出现,我想捕获Tom和Jane之间的文本。
我写了以下代码:
text = re.compile(r'''(
TOM\s*
([\w\W]+)\s*
JANE|MARY
)''', re.VERBOSE)
text_out = text.search(string).group(1)
然而,这段代码会给我Tom和Jane之间的文字,即使Mary出现在第一位。我知道这是因为管道功能从左到右读取,因此首先匹配Jane。有没有办法对此进行编码,这取决于谁首先出现在文本中?
例如,在string2中: "''' TOM 喜欢去游泳 JANE 喜欢去购物 玛丽 喜欢去操场 '''
我想捕获Tom和Jane之间的string2文本。
答案 0 :(得分:4)
您需要修复您的更改,必须使用非捕获组(?:JANE|MARY)
附加,并使用带[\w\W]
的惰性量词(我将替换为.*
并使用re.DOTALL
修饰符使点也匹配换行符:
(?s)TOM\s*(.+?)\s*(?:JANE|MARY)
请参阅regex demo
如果没有(?:...|...)
,你的正则表达式匹配Tom
,那么任何1个字符都尽可能多(也就是说,正则表达式抓住整个字符串,然后回溯以匹配最后一次出现的字符串后续子模式JANE
)和JANE
或MARY
子字符串。现在,固定的正则表达式匹配:
(?s)
- DOTALL内联修饰符TOM
- 文字字符序列\s*
- 0+ whitespaces (.+?)
- 第1组(捕获):任意1个字符,尽可能少,直到第一次出现的后续子模式.... \s*
- 0+ whitespaces (?:JANE|MARY)
- JANE
或MARY
子字符串。