正则表达式中的贪婪模式和非贪婪模式
这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。
作者:神的孩子都在歌唱
一. 贪婪模式(Greedy Mode)
定义: 贪婪模式是正则表达式的默认匹配模式。在贪婪模式下,量词会尝试匹配尽可能多的字符。贪婪量词包括 *
、+
、?
、{n,m}
等。
示例:
假设我们有以下字符串:
<a>First</a><a>Second</a>
使用贪婪模式的正则表达式 <a>.*</a>
来匹配 <a>
和 </a>
之间的内容:
import re
text = "<a>First</a><a>Second</a>"
pattern = re.compile(r"<a>.*</a>")
matches = pattern.findall(text)
print(matches)
输出:
['<a>First</a><a>Second</a>']
正则表达式 <a>.*</a>
匹配了整个字符串,因为 .*
尽可能多地匹配字符,直到最后一个 </a>
。
二. 非贪婪模式(Non-Greedy Mode)
定义: 非贪婪模式也称为懒惰模式(Lazy Mode)。在非贪婪模式下,量词会尝试匹配尽可能少的字符。非贪婪量词通过在贪婪量词后面加上一个问号 ?
来表示,例如 *?
、+?
、??
、{n,m}?
等。
示例
使用非贪婪模式的正则表达式 <a>.*?</a>
来匹配 <a>
和 </a>
之间的内容:
import re
text = "<a>First</a><a>Second</a>"
pattern = re.compile(r"<a>.*?</a>")
matches = pattern.findall(text)
print(matches)
输出:
['<a>First</a>', '<a>Second</a>']
正则表达式 <a>.*?</a>
分别匹配了两个 <a>
标签和它们之间的内容,因为 .*?
尽可能少地匹配字符,直到遇到第一个 </a>
。
三.应用场景区别
-
贪婪模式:适用于需要匹配尽可能多内容的情况。
-
非贪婪模式:适用于需要匹配尽可能少内容的情况,避免过度匹配。
作者:神的孩子都在歌唱
本人博客:https://blog.csdn.net/weixin_46654114
转载说明:务必注明来源,附带本人博客连接。
总结
在正则表达式中,理解贪婪模式和非贪婪模式的区别是编写有效匹配模式的关键。贪婪模式会尝试匹配尽可能多的字符,而非贪婪模式会尝试匹配尽可能少的字符。根据具体需求选择合适的匹配模式,可以提高正则表达式的准确性和效率。
通过上述示例和解释,希望你能更好地理解和应用正则表达式中的贪婪模式和非贪婪模式。如果你有更多问题或需要进一步的帮助,请随时联系我。
为了更好地理解这个问题,我们需要深入了解非贪婪模式(.*?
)的工作机制。
非贪婪模式的工作原理
非贪婪模式会尽可能少地匹配字符,但它仍然会尝试匹配整个正则表达式。如果在尝试匹配整个正则表达式时遇到需要匹配更多字符的情况,它会继续匹配更多的字符,以满足整个正则表达式的需求。
你的正则表达式
(?i)\bSELECT\s+(?:current_database\(\)|.*?\bFROM\s+pg_database)
让我们分析这个正则表达式在匹配以下字符串时的行为:
字符串:
SELECT * FROM dfdf FROM pg_database;
步骤分析:
-
(?i)\bSELECT\s+
匹配 "SELECT" 关键字和后面的一个或多个空白字符。 -
(?:current_database\(\)|.*?\bFROM\s+pg_database)
尝试匹配:-
current_database\(\)
: 不匹配,因为字符串中没有current_database()
-
.*?\bFROM\s+pg_database
: 非贪婪模式开始尽可能少地匹配字符
-
匹配过程
在 .*?\bFROM\s+pg_database
中,非贪婪模式会首先尝试匹配尽可能少的字符:
-
起初,
.*?
可能会匹配零个字符,然后继续看后面的模式\bFROM\s+pg_database
是否能够匹配到字符串中的内容。 -
如果
\bFROM\s+pg_database
没有匹配到(因为后面没有FROM pg_database
),非贪婪模式会逐步增加匹配的字符数量,直到满足\bFROM\s+pg_database
的条件。
示例解释
字符串:SELECT * FROM dfdf FROM pg_database;
-
SELECT
: 匹配(?i)\bSELECT\s+
-
* FROM dfdf
: 尝试最小匹配.*?
-
FROM pg_database
: 满足\bFROM\s+pg_database
即使使用了非贪婪模式,它会继续匹配更多的字符以满足整个正则表达式的条件。因此,它最终匹配了 SELECT * FROM dfdf FROM pg_database
。
改进方案
为了更准确地控制匹配结果,你可以使用更严格的正则表达式,限制非贪婪模式的匹配范围。例如,你可以明确指定 SELECT
和 FROM
之间的内容:
(?i)\bSELECT\s+(?:current_database\(\)|[^;]*?\bFROM\s+pg_database)
在这里,[^;]*?
表示匹配除分号以外的任意字符(尽可能少),直到遇到单词边界的 FROM
和 pg_database
。
示例代码
import re
# 示例文本
text = "SELECT * FROM dfdf FROM pg_database;"
# 改进的正则表达式
regex = r"(?i)\bSELECT\s+(?:current_database\(\)|[^;]*?\bFROM\s+pg_database)"
# 编译正则表达式
pattern = re.compile(regex)
# 查找匹配项
matches = pattern.findall(text)
# 输出结果
print("Text:", text)
print("Matches:", matches)
输出
Text: SELECT * FROM dfdf FROM pg_database;
Matches: ['SELECT * FROM dfdf FROM pg_database']
这种方式可以避免匹配到不需要的部分,更准确地控制匹配结果。
作者:神的孩子都在歌唱
本人博客:https://blog.csdn.net/weixin_46654114
- 点赞
- 收藏
- 关注作者
评论(0)