Python正则表达式匹配上一组中匹配的内容(多个中的一个)

ogsagwnx  于 2023-02-02  发布在  Python
关注(0)|答案(4)|浏览(133)

我有一个正则表达式(?:AA|BB)(.*)(?:AA|BB),它捕获分隔符AABB之间的所有内容。
我遇到的问题是,这也将匹配AA...BB。这是我不希望的。我如何才能使正则表达式只匹配AA...AABB...BB

utugiqy6

utugiqy61#

如果需要匹配的字符串的开头和结尾具有*相同的 * 前导和尾随分隔符,则只需捕获前导分隔符并在模式本身内部使用 * 反向引用 *:

(AA|BB)(.*)\1
^     ^    ^^

参见regex demo
在Python中,如果你只想得到你需要的组,你就必须使用re.finditer,而不是返回元组列表(因此包含AABB)的re.findall,为了匹配从AA到下一个AA的子字符串,使用惰性量词*?(AA|BB)(.*?)\1
一个简短的Python demo

import re
p = re.compile(r'(AA|BB)(.*)\1')
test_str = "AA text AA"
print([x.group(2).strip() for x in p.finditer(test_str)])
# => ['text']

如果需要匹配带有不匹配的前导和尾随分隔符的字符串,则必须使用alternation

AA(.*)AA|BB(.*)BB

或者-匹配最接近的尾随AA s和BB s的惰性限定符版本:

AA(.*?)ZZ|BB(.*?)YY

注意,这将在结果中输出空元素,因为只有一个组会被匹配,在大多数Python构建中,如果你计划在re.sub中使用这种模式,应该谨慎使用(在Python 3.5之前,不匹配的组不会用空字符串(= None)初始化,并且可能抛出异常。
下面是一个带有re.finditerextraction sample code

import re
p = re.compile(r'(AA)(.*?)(ZZ)|(BB)(.*?)(YY)')
test_str = "AA Text 1 here ZZ and BB Text2 there YY"
print("Contents:") 
print([x.group(2).strip() for x in p.finditer(test_str) if x.group(2)])
print([x.group(5).strip() for x in p.finditer(test_str) if x.group(5)])
print("Delimiters:")
print([(x.group(1), x.group(3)) for x in p.finditer(test_str) if x.group(1) and x.group(3)])
print([(x.group(4), x.group(6)) for x in p.finditer(test_str) if x.group(4) and x.group(6)])

结果:

Contents:
['Text 1 here']
['Text2 there']
Delimiters:
[('AA', 'ZZ')]
[('BB', 'YY')]

在现实生活中,对于非常长和复杂的文本,这些正则表达式可以是unrolled,以使匹配线性和高效,但这是一个不同的故事。
最后但并非最不重要的是,如果您需要将最短的子字符串从一个分隔符匹配到另一个分隔符,而该分隔符在中不包含这些分隔符,请使用tempered greedy标记

AA((?:(?!AA|ZZ).)*)ZZ|BB((?:(?!BB|YY).)*)YY
   ^^^^^^^^^^^^^^^       ^^^^^^^^^^^^^^^

请参见regex demo以了解与AA(.*?)ZZ|BB(.*?)YY的区别。

k2fxgqgv

k2fxgqgv2#

这个问题让人困惑。据我所知,您希望它匹配AA..AA或BB..BB,但不匹配当前匹配的AA..BB。我对正则表达式很不在行,但我认为这应该可以工作:
编辑:抱歉,SE格式搞砸了。

(?:(AA(.*)AA)|(BB(.*)BB))
>>> data = ['AAsometextAA', 'BBothertextBB', 'NotMatched', 'AAalsonotmatchedBB']
>>> matches = filter(lambda x: x is not None, [re.match("(?:(AA(.*)AA)|(BB(.*)BB))", datum) for datum in data])
>>> matches
[<_sre.SRE_Match object at 0x007DC078>, <_sre.SRE_Match object at 0x007DC288>]
>>> for match in matches:
...     print(match.group(0))
...
AAsometextAA
BBothertextBB
>>>
uhry853o

uhry853o3#

这应该对你有用。

(AA(.*)AA)|(BB(.*)BB)
ct3nt3jp

ct3nt3jp4#

试试这个

AA(.*)AA|BB(.*)BB

查看this示例

相关问题