Python正则表达式中的match和search的区别
今天我们来聊一个面试中常见的Python正则表达式的陷阱:match和search的区别。这个问题每次面试时都会被拿出来问,大家都觉得好像差不多,可实际一用起来,才发现这两者有着微妙的差异。程序员嘛,生活就是要时刻警惕这些坑,不然不小心就栽进去了。
好了,不卖关子了,直接进入正题。我们先简单看一下它们各自的功能。
re.match 和 re.search 的基本区别
re.match:
只在字符串的开头进行匹配。如果匹配成功,它就返回一个匹配对象;如果开头不匹配,直接返回 None。说白了, match就是个“固执的家伙”,它只认开头,不管后面的内容是啥。
re.search:
在整个字符串中进行查找,找到第一个匹配的部分就返回匹配对象;如果没有匹配的内容,它也返回 None。search比match要“宽容”一些,不管你在什么地方找到匹配,它都能接纳。
看个例子
假如我们有一个正则表达式 r'\d+',用来匹配数字。现在我们有一个字符串 '123abc',想要看看这两个函数的行为。
import repattern = r'\d+'
text = "123abc"
# 使用 match
match_result = re.match(pattern, text)
if match_result:
print("match found:", match_result.group())
else:
print("match not found")
# 使用 search
search_result = re.search(pattern, text)
if search_result:
print("search found:", search_result.group())
else:
print("search not found")
输出:
match not found
search found: 123
解释:
re.match只在字符串开头匹配,如果开头是123abc,它会尝试匹配数字,但是它需要的是从开头开始就符合正则表达式的模式,而这时它直接失败了。re.search就宽松多了,虽然字符串开头有123,它还是能找到第一个匹配项,所以成功返回了123。
正则表达式在工作中的使用
在实际工作中,我们经常需要用正则表达式来进行字符串匹配。比如我们有一个场景,需要判断一个手机号是否符合规定。
代码示例:用 re.match 判断手机号
假设我们规定手机号必须是以 1 开头,接下来是 10 位数字:
import redef validate_phone_number(phone):
pattern = r'^1\d{10}$' # 以1开头,后面跟10个数字
if re.match(pattern, phone):
return "Valid phone number"
else:
return "Invalid phone number"
# 测试
phone = "13812345678"
print(validate_phone_number(phone)) # Valid phone number
解释:
这里使用 ^来表示字符串的开头,$表示字符串的结尾,整个正则表达式就限定了手机号必须严格符合这个规则。如果是用 re.search,虽然也能找到手机号中的数字部分,但这不是我们想要的,因为我们需要确保整个字符串都是符合要求的。
代码示例:用 re.search 查找文本中的手机号
假设我们有一个长文本,要在其中查找手机号,我们就应该用 re.search 来做。
import redef find_phone_numbers(text):
pattern = r'\d{11}' # 匹配11位数字
matches = re.findall(pattern, text)
return matches
# 测试
text = "我的电话是13812345678,另一个是13998765432,赶紧联系我!"
print(find_phone_numbers(text)) # ['13812345678', '13998765432']
解释:
这里的正则表达式 \d{11}就可以匹配文本中的任何11位数字,re.search会遍历整个文本,找出所有符合条件的数字并返回。
区别小结
re.match主要用来检测字符串的开头是否符合规则。re.search则会扫描整个字符串,找到第一个符合规则的部分。
在你写代码的时候,记得根据需求来选择。比如,你只关心字符串开头的匹配,match 就是你需要的工具;如果你关心的是字符串中任意位置的匹配,那就用 search 吧。
什么时候用 re.match 或者 re.search
好吧,说了这么多,大家肯定有点困惑了,什么时候选 match,什么时候用 search?别急,我来给你总结几点经验:
**用
match**:
当你只关心字符串的开头是否符合某种模式时,使用 match。比如验证一些格式要求严格的字段,或者检查某个特定条件是否出现在开头。
**用 search**:
当你只想找出字符串中符合正则的某一部分时,使用 search。比如从一大段文本中找出某个信息,或者你只关心某个模式在哪里出现都可以。
用正则表达式时要小心
作为一个程序员,在用正则表达式的时候,千万要注意正则的贪婪性。正则默认是贪婪的,意味着它会尽可能多地匹配字符。有时你可能会遇到意料之外的匹配结果,导致代码出错。
示例:贪婪匹配与非贪婪匹配
import retext = "<div>First part</div><div>Second part</div>"
# 贪婪匹配
greedy_result = re.findall(r'<div>.*</div>', text)
print("Greedy match:", greedy_result)
# 非贪婪匹配
non_greedy_result = re.findall(r'<div>.*?</div>', text)
print("Non-greedy match:", non_greedy_result)
输出:
Greedy match: ['<div>First part</div><div>Second part</div>']
Non-greedy match: ['<div>First part</div>', '<div>Second part</div>']
解释:
贪婪匹配 .*会尽可能多地匹配字符,因此它匹配了整个字符串。非贪婪匹配 .*?则会尽可能少地匹配字符,所以它分别匹配了两个<div>标签中的内容。
总结
通过这个例子,大家可以发现,re.match 和 re.search 虽然在某些方面看起来很像,但实际用途却大有不同。使用它们时,要清楚地了解自己到底需要检查的是整个字符串的开头,还是字符串中的任意位置。毕竟,正则这个工具,不灵活的用起来可是很容易出错的。
对编程、职场感兴趣的同学,大家可以联系我微信:golang404,拉你进入“程序员交流群”。
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》。