【Python 每日一技】使得正则表达式匹配最短的字符串

文章目录

1 问题

在尝试使用正则表达式进行文本匹配时,你发现匹配出了可能的字符串中最长的字那个,但实际上你希望匹配出最短的那个。

2. 解决方案

上述问题通常发生在这样的情况下,即尝试匹配的文本被包含在了一对起始和终止分隔符之间(例如:一对双引号之间的文本)。例如:

>>> import re
>>> str_pattern = re.compile(r'\"(.*)\"')
>>> text1 = 'Computer says "no."'
>>> re.findall(r'\"(.*)\"', text1)
['no.']
>>> str_pattern.findall(text1)
['no.']
>>> text2 = 'Computer says "no." Phone says "yes."'
>>> re.findall(r'\"(.*)\"', text2)
['no." Phone says "yes.']
>>> str_pattern.findall(text2)
['no." Phone says "yes.']

在上述案例中,对于 text2 ,你可能希望匹配出 no. 以及 yes. ,而由于正则表达式 r'\"(.*)\"' 的含义是匹配在一对双引号之间除了换行符以外(在正则表达式中 . 表示除换行符以外的字符)的字符出现零次或任意多次(在正则表达式中 * 表示其之前的字符串出现零次或任意多次),即 * 的功能具有贪婪特征,因此最终匹配到的是最长结果。

为了避免这样的情况发生,只需要在 * 之后加上 ? 修饰符即可,例如:

>>> re.findall(r'\"(.*?)\"', text2)
['no.', 'yes.']
>>> str_pattern = re.compile(r'\"(.*?)\"')
>>> str_pattern.findall(text2)
['no.', 'yes.']

这就使得最终的匹配结果变为非贪婪的模式。

3. 讨论

本文提及的在使用 . 构造正则表达式的情况下比较常见,由于 . 在正则表达式中可以表示除换行符外的任意字符,因此在待匹配的文本中,中间的起始和结束分隔符(例如本文中的双引号)将会被视为成功匹配的字符串的一部分。

    原文作者:TakingCoding4Granted
    原文地址: https://blog.csdn.net/weixin_37780776/article/details/124232609
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞