正则表达式中的贪婪模式和非贪婪模式
这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。
作者:神的孩子都在歌唱
一. 贪婪模式(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)