Python 非贪婪正则表达式

Posted

技术标签:

【中文标题】Python 非贪婪正则表达式【英文标题】:Python non-greedy regexes 【发布时间】:2010-10-20 11:08:25 【问题描述】:

如果"a (b) c (d) e" python 匹配"b" 而不是"b) c (d",我该如何制作像"(.*)" 这样的python 正则表达式?

我知道我可以使用"[^)]" 而不是".",但我正在寻找一种更通用的解决方案,以使我的正则表达式更加简洁。有没有办法告诉python“嘿,尽快匹配这个”?

【问题讨论】:

【参考方案1】:

你寻求全能的*?

来自文档,Greedy versus Non-Greedy

非贪婪限定符 *?+???m,n? [...] 匹配为 little 尽可能的文字。

【讨论】:

根据 Internet 档案,所有指向的链接都是 Python "re" 模块文档的副本,因此 Trey 的链接同样有效。 这个*?的常用英文名是什么? 通配符@Trevor Boyd Smith 这被称为 "non greedy" 限定符【参考方案2】:
>>> x = "a (b) c (d) e"
>>> re.search(r"\(.*\)", x).group()
'(b) c (d)'
>>> re.search(r"\(.*?\)", x).group()
'(b)'

According to the docs:

*”、“+”和“?”限定符都是贪婪的;它们匹配尽可能多的文本。有时这种行为是不需要的;如果 RE <.*> 与“<H1>title</H1>”匹配,它将匹配整个字符串,而不仅仅是“<H1>”。在限定符之后添加 '?' 使其以非贪婪或最小方式执行匹配;将匹配尽可能少的字符。在前面的表达式中使用 .*? 将只匹配 '<H1>'。

【讨论】:

我尝试了一个不同的,它总是那么贪婪:>>> re.search("\(.+?$", x).group() '(b) c (d) e' 我希望最后一个 ( 到该行的末尾,但它给出了第一个 ( 到末尾行。关于如何解释这一点以及如何实现“最后(到行尾”)的任何建议?【参考方案3】:

\\(.*?\\) 不行吗?那是非贪婪的语法。

【讨论】:

【参考方案4】:

使用不贪婪的匹配是一个好的开始,但我还建议您重新考虑使用 .* —— 那怎么样?

groups = re.search(r"\([^)]*\)", x)

【讨论】:

【参考方案5】:

你想让它匹配“(b)”吗?按照 Zitrax 和 Paolo 的建议去做。你想让它匹配“b”吗?做

>>> x = "a (b) c (d) e"
>>> re.search(r"\((.*?)\)", x).group(1)
'b'

【讨论】:

【参考方案6】:

正如其他人所说,使用 ? * 量词上的修饰符将解决您的直接问题,但要小心,您开始误入正则表达式停止工作的区域,而您需要一个解析器。例如,字符串“(foo (bar)) baz”会给你带来麻烦。

【讨论】:

【参考方案7】:

首先,我不建议在正则表达式中使用“*”。是的,我知道,它是最常用的多字符分隔符,但它仍然是个坏主意。这是因为,虽然它确实匹配该字符的任何重复次数,但“任何”包含 0,这通常是您想要抛出语法错误而不是接受的东西。相反,我建议使用+ 符号,它匹配长度> 1 的任何重复。此外,据我所知,您正在处理固定长度的括号表达式。因此,您可能可以使用x, y 语法来专门指定所需的长度。

但是,如果你真的需要非贪婪的重复,我建议咨询全能的?。当放置在任何正则表达式重复说明符的末尾时,这将强制正则表达式的该部分找到尽可能少的文本。

话虽如此,我会非常小心?,就像 Dr. Who 中的 Sonic 螺丝刀一样,如果不仔细校准的话,我应该怎么写,“有点”不受欢迎的东西.例如,要使用您的示例输入,它会将 ((1)(注意缺少第二个 rparen)标识为匹配项。

【讨论】:

以上是关于Python 非贪婪正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

python正则表达式贪婪算法与非贪婪算法与正则表达式子模式的简单应用

Python 非贪婪正则表达式

python-正则表达式

第11.9节 Python正则表达式的贪婪模式和非贪婪模式

15.python正则匹配 元字符转义重复或捕获分组断言:零度断言负向零宽断言贪婪非贪婪引擎选项

python基础:正则re模块贪婪和非贪婪