正则表达式一个接一个捕获多个短语

时间:2013-10-06 18:26:23

标签: python regex

我正在试图弄清楚如何使正则表达式只捕获一堆特定事物之后的物品。我正在使用Python。这样的事情的一个例子是使用文本B <4>.<5> <6> A <1> m<2> . <3>,目的是仅捕获1,2和3.我认为像A.*?<(.+?)>这样的正则表达式可以工作,但它只能捕获最后的3个使用Python re.findall。我可以得到任何帮助吗?

3 个答案:

答案 0 :(得分:2)

regex module(在将来的pythons中将替换re)支持变量lookbehinds,这使得它非常简单:

s = "B <4>.<5> <6> A23 <1> m<2> . <3>"

import regex
print regex.findall(r'(?<=A\d+.*)<.+?>', s)
# ['<1>', '<2>', '<3>']

(我正在使用A\d+而非A来使事情变得有趣。如果你被绑定到股票re,你就会被迫做出像这样丑陋的变通办法:

import re
print re.findall(r'(<[^<>]+>)(?=(?:.(?!A\d+))*$)', s)
# ['<1>', '<2>', '<3>']

或预拆分:

print re.findall(r'<.+?>', re.split(r'A\d+', s)[-1])

答案 1 :(得分:1)

使用可变宽度的lookbehind会更容易,但替代方法可能是确保在匹配的部分之后没有A,以便您可以使用以下内容:

re.findall(r'<(.+?)>(?![^A]*A[^A]*$)', 'B <4>.<5> <6> A <1> m<2> . <3>')

但是这里有一个问题...... (.+?)接受任何,可以打破你正在寻找的东西。您可以使用否定的类:[^>]+而不是.+?

这意味着:

re.findall(r'<([^>]+)>(?![^A]*A[^A]*$)', 'B <4>.<5> <6> A <1> m<2> . <3>')

regex101 demo

(?![^A]*A[^A]*$)确保在您捕获的部分之前没有A

(?! ... )是一个负向前瞻,如果内部匹配,匹配就会失败。

[^A]*匹配除A

之外的任何字符

$匹配字符串的结尾。

答案 2 :(得分:1)

目前的情况是,您的代码与<>之间的文字匹配,该文字位于A之后,后跟零个或多个字符。此外,满足此条件的文本中唯一的部分是<1>(这就是返回所有内容的原因。)

有很多方法可以解决这个问题,但我认为最简单的方法是首先拆分A,然后使用<(.+?)>

>>> from re import findall, split
>>> text = 'B <4>.<5> <6> A <1> m<2> . <3>'
>>> text = split('A', 'B <4>.<5> <6> A <1> m<2> . <3>')
>>> text
['B <4>.<5> <6> ', ' <1> m<2> . <3>']
>>> text = text[1]
>>> text
' <1> m<2> . <3>'
>>> text = findall('<(.+?)>', text)
>>> text
['1', '2', '3']
>>>

以上是一步一步的演示。以下是您需要的代码:

>>> text = 'B <4>.<5> <6> A <1> m<2> . <3>'
>>> findall('<(.+?)>', split('A', text)[1])
['1', '2', '3']
>>>