📝 面试求职: 「面试试题小程序」 ,内容涵盖 测试基础、Linux操作系统、MySQL数据库、Web功能测试、接口测试、APPium移动端测试、Python知识、Selenium自动化测试相关、性能测试、性能测试、计算机网络知识、Jmeter、HR面试,命中率杠杠的。(大家刷起来…)
📝 职场经验干货:
在正则表达式中,贪婪匹配(Greedy Matching)和非贪婪匹配(Non-greedy Matching,也称为懒惰匹配 Lazy Matching)是指量词(如 *, +, ? 和 {})如何与文本匹配的方式。理解这两者的区别对于编写有效的正则表达式至关重要。
贪婪匹配
默认情况下,正则表达式的量词是贪婪的。这意味着它们会尽可能多地匹配字符。换句话说,当遇到可以匹配多个字符的情况时,贪婪模式会选择最长的可能匹配。
示例:
import re
text = "Here issometext withtags."
pattern = r'<.*>'
match = re.search(pattern, text)
print(match.group()) # 输出:sometext withtags
在这个例子中,<.*> 试图找到以 < 开始并以 > 结束的最大字符串。因此,它从第一个 < 开始直到最后一个 > 结束,包括中间的所有内容。
非贪婪匹配
如果你希望量词尽可能少地匹配字符,你可以使用非贪婪模式。这通常通过在量词后面添加一个问号 ? 来实现。这样,匹配器会在满足条件的情况下尽早停止扩展匹配范围。
示例:
import re
text = "Here issometext withtags."
pattern = r'<.*?>'
matches = re.findall(pattern, text)
print(matches) # 输出: ['', '', '', '']
这里,<.*?> 尽可能少地匹配字符,因此每次遇到 > 它就会停止当前匹配,并开始寻找下一个匹配项。结果是得到了所有单独的标签,而不是整个字符串作为一个大匹配。
关键点总结:
贪婪模式 (*, +, ?, {}): 默认行为,尽可能多地匹配。
非贪婪模式 (*?, +?, ??, {n,m}?): 在满足条件的前提下,尽可能少地匹配。
选择贪婪还是非贪婪模式取决于你想要解析的数据结构以及你希望如何分割或提取这些数据。理解这一点可以帮助你更精确地控制正则表达式的匹配行为。
正则表达式中贪婪匹配和非贪婪匹配的优先级是什么?
在正则表达式中,贪婪匹配和非贪婪匹配的优先级并不是通过“优先级”这个概念来描述的,而是取决于量词后是否跟随有使它变为非贪婪(懒惰)模式的问号 ?。默认情况下,量词是贪婪的,这意味着它们会尽可能多地匹配字符;而当你在量词后面加上一个问号 ? 时,就会变成非贪婪或称为懒惰模式,这时它们会尽可能少地匹配字符。
贪婪 vs 非贪婪匹配
贪婪匹配:量词(如 *, +, ?, {n,m} 等)默认为贪婪模式,即尽可能多地匹配字符。
非贪婪匹配:通过在量词后面添加一个问号 ? 来实现,例如 *?, +?, ??, {n,m}?,这会让匹配器尽可能少地匹配字符。
关于“优先级”
实际上,在这里讨论的不是传统意义上的运算符优先级,而是匹配行为的选择。当正则表达式引擎执行匹配操作时,如果量词后面跟着一个 ?,那么该量词将以非贪婪的方式工作,否则以贪婪的方式工作。
贪婪匹配示例:
import re
text = "Here issometext withtags."
pattern = r'<.*>'
match = re.search(pattern, text)
print(match.group()) # 输出:sometext withtags
在这个例子中,<.*> 尽可能多地匹配,直到找到最后一个 >。
非贪婪匹配示例:
import re
text = "Here issometext withtags."
pattern = r'<.*?>'
matches = re.findall(pattern, text)
print(matches) # 输出: ['', '', '', '']
使用 <.*?>,匹配器会在遇到第一个 > 时停止当前匹配,并继续寻找下一个匹配项,因此每个标签都被单独匹配出来。
正则表达式中贪婪匹配和非贪婪匹配的例子有哪些?
贪婪匹配
默认情况下,量词是贪婪的,这意味着它们会尽可能多地匹配字符。
示例 1:匹配 HTML 标签(贪婪模式)
import re
text = "
First
Second
"
pattern_greedy = r"
.*
"
# 使用贪婪模式进行搜索
matches = re.findall(pattern_greedy, text)
print(matches) # 输出: ['
First
Second
']
在这个例子中,.* 尽可能多地匹配字符,直到最后一个 结束标签被找到。
非贪婪匹配
在量词后面加上一个问号 ? 可以将贪婪模式转换为非贪婪模式,这样它们就会尽可能少地匹配字符。
示例 2:匹配 HTML 标签(非贪婪模式)
import re
text = "
First
Second
"
pattern_non_greedy = r"
.*?
"
# 使用非贪婪模式进行搜索
matches = re.findall(pattern_non_greedy, text)
print(matches) # 输出: ['
First
', '
Second
']
在这个例子中,.*? 在遇到第一个 结束标签时就停止匹配,因此每个
标签及其内容都被单独识别出来。
示例 3:匹配重复单词(贪婪 vs 非贪婪)
import re
text = "This is a test test sentence."
# 贪婪模式
pattern_greedy = r"(\b\w+\b)\s+\1"
match_greedy = re.search(pattern_greedy, text)
if match_greedy:
print("Greedy Match:", match_greedy.group(0)) # 输出: Greedy Match: test test
# 非贪婪模式
pattern_non_greedy = r"(\b\w+\b)\s+?\1"
match_non_greedy = re.search(pattern_non_greedy, text)
if match_non_greedy:
print("Non-Greedy Match:", match_non_greedy.group(0)) # 输出: Non-Greedy Match: test test
在这个例子中,虽然结果相同,但主要是为了展示如何使用不同的匹配方式。实际上,在这个特定的情况下,是否使用非贪婪模式对结果没有影响,因为 \s+ 已经能够满足需求。
示例 4:匹配路径中的文件名(贪婪 vs 非贪婪)
import re
path = "/home/user/documents/report.docx"
# 贪婪模式 - 匹配到最后一个斜杠之后的所有字符
pattern_greedy = r".*/(.*)"
match_greedy = re.search(pattern_greedy, path)
if match_greedy:
print("Greedy File Name:", match_greedy.group(1)) # 输出: Greedy File Name: report.docx
# 非贪婪模式 - 这里非贪婪模式并不适用,因为我们要的是从最后一个斜杠到字符串结束的内容
pattern_non_greedy = r".*?/(.*)"
match_non_greedy = re.search(pattern_non_greedy, path)
if match_non_greedy:
print("Non-Greedy File Name:", match_non_greedy.group(1)) # 输出: Non-Greedy File Name: documents/report.docx
这里展示了贪婪模式可以用来提取整个路径中最后的部分(即文件名),而非贪婪模式可能会导致不期望的结果,因为它试图尽早结束匹配。
总结
贪婪模式 (*, +, ?, {n,m}): 默认行为,尽可能多地匹配。
非贪婪模式 (*?, +?, ??, {n,m}?): 在满足条件的前提下,尽可能少地匹配。
选择贪婪还是非贪婪模式取决于你想要解析的数据结构以及你希望如何分割或提取这些数据。理解这一点可以帮助你更精确地控制正则表达式的匹配行为。
最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】