5

这是示例:

a = "one two three four five six one three four seven two"
m = re.search("one.*four", a)

我想要的是找到从“一”到“四”的子字符串,其中不包含子字符串“二”。答案应该是:m.group(0) = "一三四", m.start() = 28, m.end() = 41

有没有办法用一条搜索线做到这一点?

4

4 回答 4

7

您可以使用此模式:

one(?:(?!two).)*four

在匹配任何其他字符之前,我们检查我们是否开始匹配“两个”。

工作示例:http ://regex101.com/r/yY2gG8

于 2013-11-03T06:10:19.537 回答
2

您可以使用否定的前瞻断言(?!...)

re.findall("one(?!.*two).*four", a)
于 2013-11-03T05:26:17.120 回答
1

随着更硬的字符串 Satoru 添加,这有效:

>>> import re
>>> a = "one two three four five six one three four seven two"
>>> re.findall("one(?!.*two.*four).*four", a)
['one three four']

但是 - 总有一天 - 你真的会后悔编写棘手的正则表达式。如果这是我需要解决的问题,我会这样做:

for m in re.finditer("one.*?four", a):
    if "two" not in m.group():
        break

我在那里使用了最小匹配(.*?),这已经够棘手了。正则表达式可能是一个真正的痛苦:-(

编辑:大声笑!但是如果你让字符串更难,顶部的更混乱的正则表达式会再次失败:

a = "one two three four five six one three four seven two four"

最后:这是一个正确的解决方案:

>>> a = 'one two three four five six one three four seven two four'
>>> m = re.search("one([^t]|t(?!wo))*four", a)
>>> m.group()
'one three four'
>>> m.span()
(28, 42)

我知道你说你想m.end()成为 41 岁,但那是不正确的。

于 2013-11-03T06:05:17.580 回答
0

另一种带有非常简单图案的衬里

import re
line = "one two three four five six one three four seven two"

print [X for X in [a.split()[1:-1] for a in 
                     re.findall('one.*?four', line, re.DOTALL)] if 'two' not in X]

给我

>>> 
[['three']]
于 2013-11-03T08:50:31.440 回答