0

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

4

3 回答 3

2

regex模块(将re在未来的 python 中替换)支持变量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为了让事情变得有趣)。如果您绑定到 stock re,您将被迫采用如下丑陋的解决方法:

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

或预拆分:

print re.findall(r'<.+?>', re.split(r'A\d+', s)[-1])
于 2013-10-06T18:49:00.363 回答
1

使用可变宽度后视会更容易,但替代方法可能是确保在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>')

正则表达式101演示

(?![^A]*A[^A]*$)确保你正在捕捉的部分没有A前面。

(?! ... )是一个负前瞻,如果里面的内容匹配,则匹配失败。

[^A]*匹配任何字符,除了A

$匹配字符串的结尾。

于 2013-10-06T18:33:02.047 回答
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']
>>>
于 2013-10-06T18:33:13.627 回答