正则表达式中的贪婪模式和非贪婪模式

举报
神的孩子在歌唱 发表于 2024/09/30 09:21:30 2024/09/30
【摘要】 正则表达式中的贪婪模式和非贪婪模式这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。作者:神的孩子都在歌唱一. 贪婪模式(Greedy Mode)定义: 贪婪模式是正则表达式的默认匹配模式。在贪婪模式下,量词会尝试匹配尽可能多的字符。贪婪量词包括 *、+、?、{n,m} 等。示例:假设我们有以下字符串:<a>First</a><a>Second</a>使用贪婪模式的...

正则表达式中的贪婪模式和非贪婪模式


这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。

作者:神的孩子都在歌唱

一. 贪婪模式(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;

步骤分析:

  1. (?i)\bSELECT\s+ 匹配 "SELECT" 关键字和后面的一个或多个空白字符。

  2. (?: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;

  1. SELECT: 匹配 (?i)\bSELECT\s+

  2. * FROM dfdf: 尝试最小匹配 .*?

  3. FROM pg_database: 满足 \bFROM\s+pg_database

即使使用了非贪婪模式,它会继续匹配更多的字符以满足整个正则表达式的条件。因此,它最终匹配了 SELECT * FROM dfdf FROM pg_database

改进方案

为了更准确地控制匹配结果,你可以使用更严格的正则表达式,限制非贪婪模式的匹配范围。例如,你可以明确指定 SELECTFROM 之间的内容:

(?i)\bSELECT\s+(?:current_database\(\)|[^;]*?\bFROM\s+pg_database)

在这里,[^;]*? 表示匹配除分号以外的任意字符(尽可能少),直到遇到单词边界的 FROMpg_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

转载说明:务必注明来源,附带本人博客连接。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。