2.5 字符串�索和替�¶

问题¶

你想在字符串中�索和匹�指定的文本模�

解决方案¶

对于简�的字�模�,直接使用 str.replace() 方法��,比如:

>>> text = 'yeah, but no, but yeah, but no, but yeah'
>>> text.replace('yeah', 'yep')
'yep, but no, but yep, but no, but yep'
>>>

对于��的模�,请使用 re 模�中的 sub() 函数。 为了说明这个,�设你想将形�为 11/27/2012 的日期字符串改� 2012-11-27 。示例如下:

>>> text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
>>> import re
>>> re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text)
'Today is 2012-11-27. PyCon starts 2013-3-13.'
>>>

sub() 函数中的第一个�数是被匹�的模�,第二个�数是替�模�。�斜�数字比如 \3 指���模�的�获组�。

如果你打算用相�的模��多次替�,考虑先编译它���性能。比如:

>>> import re
>>> datepat = re.compile(r'(\d+)/(\d+)/(\d+)')
>>> datepat.sub(r'\3-\1-\2', text)
'Today is 2012-11-27. PyCon starts 2013-3-13.'
>>>

如果你使用了命�分组,那么第二个�数请使用 \g<group_name> ,如下

>>> text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
>>> import re
>>> re.sub(r'(?P<month>\d+)/(?P<day>\d+)/(?P<year>\d+)', r'\g<year>-\g<month>-\g<day>', text)
'Today is 2012-11-27. PyCon starts 2013-3-13.'
>>>

对于更加��的替�,�以传递一个替�回调函数�代替,比如:

>>> from calendar import month_abbr
>>> def change_date(m):
... mon_name = month_abbr[int(m.group(1))]
... return '{} {} {}'.format(m.group(2), mon_name, m.group(3))
...
>>> datepat.sub(change_date, text)
'Today is 27 Nov 2012. PyCon starts 13 Mar 2013.'
>>>

一个替�回调函数的�数是一个 match 对象,也就是 match() 或者 find() 返回的对象。 使用 group() 方法���特定的匹�部分。回调函数最�返回替�字符串。

如果除了替��的结果外,你还想知�有多少替��生了,�以使用 re.subn() �代替。比如:

>>> newtext, n = datepat.subn(r'\3-\1-\2', text)
>>> newtext
'Today is 2012-11-27. PyCon starts 2013-3-13.'
>>> n
2
>>>

讨论¶

关于正则表达��索和替�,上�演示的 sub() 方法基本已�涵盖了所有。 其实最难的部分就是编写正则表达�模�,这个最好是留给读者自己去练习了。