多线和dotall的非贪婪行为

时间:2016-05-10 15:19:35

标签: python regex

我有以下字符串,我尝试将相应的'foo'中的字符串与'bar = 1','bar = 2'或'bar = 3'匹配。所以一次只能匹配一次。

file_header

foo lorem ipsum \pope
24 dolor sit amet, consectetur adipisici elit
Excepteur sint obcaecat cupiditat non 
gnu blu bar=1

foo lorem ipsum \
@>@!@ consectetur adipisici elit
gnu blu bar=2
foo lorem ipsum
23 dolor sit amet, consectetur adipisici elit
gnu blu bar=3

foo ... etc

我尝试了所有内容,从简单的^foo.*?bar=2$到类似^(?!\bfoo\b.*\bfoo\b).*\bfoo\b.*bar=2$的内容。但是在激活multiline和dotall的情况下,它将始终匹配第一个'foo'或甚至标记整个文件头。 :(

使用multiline和dotall时,似乎不可能出现非贪婪的行为。

3 个答案:

答案 0 :(得分:1)

您可以使用像

这样的驯化贪婪令牌
^foo(?:(?!^foo|bar=2$).)*bar=2$

(?:(?!^foo|bar=2$).)*匹配任何非foo的文本(在行/字符串的开头),而不是行/字符串末尾的bar=2

请参阅regex demo。但是,这样的构造是消耗资源的,建议将其展开。这是一个选项:

^foo[^\nb]*(?:\n(?!foo)[^\nb]*|b(?!ar$)[^\nb]*)*bar=2$

请参阅another demo

答案 1 :(得分:1)

此程序查找AxisView的所有非重叠事件。请注意使用此表达式在foo <stuff> bar=<number> - 模式下成功使用非贪婪运算符:re.MULTILINE

^foo.*?bar=\d+$

结果:

import re
from pprint import pprint

data = '''
file_header

foo lorem ipsum \pope
24 dolor sit amet, consectetur adipisici elit
Excepteur sint obcaecat cupiditat non 
gnu blu bar=1

foo lorem ipsum \
@>@!@ consectetur adipisici elit
gnu blu bar=2
foo lorem ipsum
23 dolor sit amet, consectetur adipisici elit
gnu blu bar=3
'''

matches = re.findall(r'^foo.*?bar=\d+$', data, re.DOTALL|re.MULTILINE)
pprint (matches)

答案 2 :(得分:1)

贪婪从左到右

它与MULTILINEDOTALL无关,它是非贪婪的运算符 只影响比赛的结束,而不是开始。

为了满足您的愿望,请在您的模式前添加.*

>>> re.findall(r'.*(foo.*?bar=1)', s, re.DOTALL)
['foo lorem ipsum \\pope\n24 dolor sit amet, consectetur adipisici elit\nExcepteur sint obcaecat cupiditat non \ngnu blu bar=1']
>>> re.findall(r'.*(foo.*?bar=2)', s, re.DOTALL)
['foo lorem ipsum @>@!@ consectetur adipisici elit\ngnu blu bar=2']
>>> re.findall(r'.*(foo.*?bar=3)', s, re.DOTALL)
['foo lorem ipsum\n23 dolor sit amet, consectetur adipisici elit\ngnu blu bar=3']