2.6 字符串忽略大小写的搜索替换

问题描述:需要以忽略大小写的方式搜索与替换文本字符串
解决方案
为了在文本操作时忽略大小写,需要在使用re模块时给这些操作提供re.IGNORECASE标志参数。例如:

>>> text='UPPER PYTHON,lower python,Mixed Python'
>>> import re
>>> re.findall('python',text,flags=re.IGNORECASE)
['PYTHON', 'python', 'Python']
>>> re.sub('python','snake',text,flags=re.IGNORECASE)
'UPPER snake,lower snake,Mixed snake'

最后的例子有个缺陷:替换字符串并不自动与被匹配字符串的大小写保持一致。
讨论
对于一般的忽略大小写的匹配操作,简单的传递一个re.IGNORECASE标志参数已经足够。

2.7 最短匹配模式

问题描述:正试着用正则表达匹配某个文本模式,但是它找到的是模式的最长可匹配。现想修改它编程查找最短的可能匹配。
解决方案
这个问题一般出现在需要匹配一对分隔符之间的文本时(比如引号包含的字符串)。考虑如下例子:

>>> str_pat=re.compile(r'\"(.*)\"')
>>> text1='Computer says "no".'
>>> str_pat.findall(text1)
['no']
>>> text2='Computer says "no".Please says "yes".'
>>> str_pat.findall(text2)
['no".Please says "yes']

这个例子中,模式的意图是匹配被双引号包含的文本。但是在正则表达式中*操作符是贪婪的,因此匹配操作会查找最长的可能匹配。于是在第二个例子中搜索text2时返回结果并不是想要的。
为修正此问题,可在模式中的*操作符后面加上?修饰符,如下所示:

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

这样使得匹配变成非贪婪模式,从而得到最短的匹配。
讨论
这一节展示了写在包含点(.)字符的正则表达式的时候遇到的一些常见问题。在一个模式字符串中,点(.)匹配除了换行外的任何字符。然而,如果将点(.)号放在开始于结束符(如引号)之间时,那么匹配操作会查找符合模式的最长可能匹配。这样通常会导致很多中间的被开始于结束符包含的文本被忽略掉,并最终被包含在匹配结果字符串中返回。通过在*或者+这样的操作符后面添加一个?可以强制匹配算法改成寻找最短的可能匹配。