Python 非贪婪正则表达式
- 2024-12-31 08:37:00
- admin 原创
- 110
问题描述:
我如何制作一个像"(.*)"
这样的 python 正则表达式,给定"a (b) c (d) e"
python 匹配"b"
而不是"b) c (d"
?
我知道我可以使用"[^)]"
代替"."
,但我正在寻找一种更通用的解决方案,使我的正则表达式更简洁一些。有什么方法可以告诉 python“嘿,尽快匹配这个”?
解决方案 1:
你寻求全能的*?
从文档中,贪婪与非贪婪
非贪婪限定符
*?
、+?
、??
或{m,n}?
[...] 匹配尽可能少的
文本。
解决方案 2:
>>> x = "a (b) c (d) e"
>>> re.search(r"(.*)", x).group()
'(b) c (d)'
>>> re.search(r"(.*?)", x).group()
'(b)'
根据文档:
'
*
'、'+
' 和 '?
' 限定符都是贪婪的;它们匹配尽可能多的文本。有时这种行为是不希望的;如果 RE<.*>
与 ' ' 匹配<H1>title</H1>
,它将匹配整个字符串,而不仅仅是 '<H1>
'。在限定符后添加 ' ' 使其以非贪婪或最小方式执行匹配;将匹配尽可能少的字符。在前面的表达式中?
使用将仅匹配 ' '。.*?
`<H1>`
解决方案 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:
您可以修改正则表达式模式以使用非贪婪量词。(.*)
您可以使用代替(.*?)
。
以下是解释:
*
是一个贪婪量词,它匹配尽可能多的内容(在您的情况下包括括号),直到最后一次出现)
。*?
是 的非贪婪(或懒惰)版本.*
,它匹配尽可能少的字符,同时仍允许整体模式匹配。只要正则表达式模式的后续部分可以匹配,它就会停止。
因此,您的正则表达式模式可以调整为(.*?)
如下形式:
import re input_string = "a (b) c (d) e" pattern = r'((.*?))' matches = re.findall(pattern, input_string) print(matches) # Output: ['b', 'd']
在这个修改后的模式中r'((.*?))'
,我们()
以非贪婪的方式匹配括号内的子字符串。该.*?
部分确保正则表达式引擎在遇到第一个右括号时立即停止捕获字符)
,从而为您提供仅匹配每对括号内内容的所需结果。
解决方案 8:
首先,我不建议在正则表达式中使用“*”。是的,我知道,它是最常用的多字符分隔符,但它仍然是一个坏主意。这是因为,虽然它确实匹配该字符的任何重复次数,但“任何”包括 0,这通常是您想要抛出语法错误而不是接受的东西。相反,我建议使用符号+
,它匹配长度 ≥ 1 的任何重复。更重要的是,据我所知,您正在处理固定长度的括号表达式。因此,您可能可以使用语法{x, y}
来具体指定所需的长度。
但是,如果你确实需要非贪婪重复,我建议咨询万能的?
。当将其放在任何正则表达式重复说明符的末尾时,将强制正则表达式的该部分找到尽可能少的文本。
话虽如此,我还是会非常小心地使用?
它,因为它就像《神秘博士》中的 Sonic Screwdriver 一样,如果不仔细校准,往往会做出“稍微”不理想的事情。例如,使用您的示例输入,它会识别((1)
(注意缺少第二个 rparen)为匹配项。