【Python 每日一技】文本查找和替换

1 问题

你希望查找并替换一段文本中的模式串。

2. 解决方案

如果以简单的字符串字面量形式给出模式串,那么你通常可以使用基本的字符串方法如 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.'

re.sub() 函数中,第一个参数用于文本匹配的正则表达式,第二个参数是用于进行替换的文本模式,其中的反斜杠加数字如 \3 指的是第一个参数中的捕捉分组编号。

如果你希望使用某个正则表达式进行多次重复的文本匹配,那么可以考虑提前对其进行编译以提高执行的速度。例如:

>>> text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
>>> import re
>>> date_pattern = re.compile(r'(\d+)/(\d+)/(\d+)')
>>> date_pattern.sub(r'\3-\1-\2', 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))
... 
>>> re.sub(r'(\d+)/(\d+)/(\d+)', change_date, text)
'Today is 27 Nov 2012. PyCon starts 13 Mar 2013.'
>>> date_pattern.sub(change_date, text)
'Today is 27 Nov 2012. PyCon starts 13 Mar 2013.'

如上所述,作为输入,传入替换回调函数的实参是类似 match()find() 以及 search() 等函数返回的匹配对象。在回调函数中通过调用匹配对象的 group() 方法以剥离出想要的部分。

如果你除了想获取替换后的文本之外,还希望知道发生了多少次替换,那么可以使用 re.subn() 函数,例如:

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

3. 讨论

对于使用正则表达式进行文本的搜索和替换,基本上都逃不过上述 re.sub() 函数的用法。实际上,最有挑战性是其实是写出正确的正则表达式。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,下面是串的查找替换课程设计的大致思路: 1. 串的查找 串的查找可以使用很多算法,例如暴力匹配、KMP算法、BM算法、Sunday算法等。以下是KMP算法的思路: (1)预处理模式串,生成next数组; (2)进行匹配时,从文本串的第一个字符开始进行匹配,若匹配则指针都向右移动一位,若不匹配则根据next数组进行移动,将模式串的指针移到最大匹配位置。 2. 串的替换 串的替换可以使用简单的遍历进行,但这种方法时间复杂度较高。可以使用KMP算法的next数组,记录匹配的位置,然后将文本串中的匹配位置替换为新的字符串。 以下是大致的代码实现: 1. KMP算法的实现: ```cpp void getNext(char *pattern, int *next) { int len = strlen(pattern); next[0] = -1; int k = -1; int j = 0; while (j < len - 1) { if (k == -1 || pattern[k] == pattern[j]) { k++; j++; if (pattern[k] != pattern[j]) { next[j] = k; } else { next[j] = next[k]; } } else { k = next[k]; } } } int kmp(char *text, char *pattern) { int tlen = strlen(text); int plen = strlen(pattern); int *next = new int[plen]; getNext(pattern, next); int i = 0; int j = 0; while (i < tlen && j < plen) { if (j == -1 || text[i] == pattern[j]) { i++; j++; } else { j = next[j]; } } delete[] next; if (j == plen) { return i - j; } else { return -1; } } ``` 2. 串的替换: ```cpp void replace(char *text, char *pattern, char *replace) { int tlen = strlen(text); int plen = strlen(pattern); int rlen = strlen(replace); int idx = kmp(text, pattern); while (idx != -1) { if (rlen == plen) { for (int i = 0; i < rlen; i++) { text[idx + i] = replace[i]; } } else if (rlen > plen) { for (int i = 0; i < rlen - plen; i++) { for (int j = tlen; j > idx + plen; j--) { text[j + rlen - plen - 1] = text[j - 1]; } tlen += rlen - plen; } for (int i = 0; i < rlen; i++) { text[idx + i] = replace[i]; } } else { for (int i = tlen; i > idx + plen; i--) { text[i + rlen - plen - 1] = text[i - 1]; } tlen += rlen - plen; for (int i = 0; i < rlen; i++) { text[idx + i] = replace[i]; } } idx = kmp(text, pattern); } } ``` 以上是串的查找替换的大致思路和代码实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值