- 读文档的意义在于知道别人已经实现了什么,怎么用
- 读源码的意义在于知道轮子是怎么造出来的
- 要好好学英语
用了三天的时间造了一个方形轮子,记录下来以吸取教训。
需求是用正则匹配一段文章,有n个匹配项,指定删除其中的某一个(第1个/第2个/倒数第1个...)
Python re库的文档是英文的,在提不起兴趣一句一句翻译下,从这里开始走上了一条岔路。
错误的实现思路:
import re
str1 = 'a1b1c1d1e.a2b2c2d2e.a3b3c3d3e.a4b4c4d4e.a5b5c5d5e.'
rules = {
'a\d{1}': 2,
'b\d{1}': -1,
'c\d{1}': -3,
'd\d{1}': -3,
}
for (reg, index) in rules.items():
if index < 0: # 反向匹配
front = str1
rear = ''
for i in range(abs(index)):
try:
_front_ = re \
.search(r'.*(?=' + reg + ')', front) \
.group()
_cur_ = re \
.search(r'' + reg + '$', re.search(r'.*(' + reg + ')', front).group()) \
.group()
_rear_ = re.compile(r'.*(' + reg + ')').sub('', front)
except AttributeError:
break
else:
if i != (-1 - index):
rear = _cur_ + _rear_ + rear
else:
rear = _rear_ + rear
front = _front_
else: # 正向匹配
front = ''
rear = str1
for i in range(index + 1):
try:
obj = re.search(r'' + reg, rear)
start = obj.start()
end = obj.end()
_front_ = rear[0:start]
_rear_ = rear[end:]
_cur_ = rear[start:end]
except AttributeError:
break
else:
if i != index:
front = front + _front_ + _cur_
else:
front = front + _front_
rear = _rear_
str1 = front + rear
print(str1)
正确的实现思路:
re.finditer()返回的对象中包含了匹配项的开始/结束位置,只要把前后内容拼起来,丢弃匹配的位置就可以了。
import re
str1 = 'a1b1c1d1e.a2b2c2d2e.a3b3c3d3e.a4b4c4d4e.a5b5c5d5e.'
rules = {
'a\d{1}': 2,
'b\d{1}': -1,
'c\d{1}': -3,
'd\d{1}': -3,
}
for (reg, index) in rules.items():
pos = [(m.start(0), m.end(0)) for m in re.finditer(reg, str1)][index]
print(pos)
front = str1[:pos[0]]
rear = str1[pos[1]:]
str1 = front + rear
print(str1)
轮子跑起来后运行情况很糟糕,65000条数据清洗4条正则匹配项花了10分钟,更换完轮子方法后只用了2分钟。