我是Python的新手,我正在编写一系列脚本来转换某些专有的标记格式。我在文件上逐行迭代,然后基本上做了大量(100-200)的替换,基本上分为4类:
line = line.replace("-","<EMDASH>") # Replace single character with tag
line = line.replace("<\\@>","@") # tag with single character
line = line.replace("<\\n>","") # remove tag
line = line.replace("\xe1","•") # replace non-ascii character with entity
str.replace()函数似乎非常有效(当我检查分析输出时,数字相当低),但是有更好的方法吗?我已经看到re.sub()方法使用函数作为参数,但我不确定这是否会更好?我想这取决于Python在内部做了哪种优化。我想在创建一个可能不太有用的大字典之前我会先征求一些建议!
另外,我做了一些标签解析(看起来有点像HTML,但不是HTML)。我确定了这样的标签:
m = re.findall('(<[^>]+>)',line)
然后在匹配的标签内进行~100次搜索/替换(主要是删除匹配),例如:
m = re.findall('(<[^>]+>)',line)
for tag in m:
tag_new = re.sub("\*t\([^\)]*\)","",tag)
tag_new = re.sub("\*p\([^\)]*\)","",tag_new)
# do many more searches...
if tag != tag_new:
line = line.replace(tag,tag_new,1) # potentially problematic
这里有效率的想法吗?
谢谢!
答案 0 :(得分:3)
str.replace()
会更有效,如果您需要复杂的模式匹配,re.sub
(显然)更有效(因为否则您必须使用str.replace
几次)。
我建议您使用两者的组合。如果您有多个模式都被一件事取代,请使用re.sub
。如果您只是需要将一个特定标记替换为另一个特定标记,请使用str.replace
。
您还可以通过使用更大的字符串来提高效率(每次调用re.sub
一次而不是一次)。增加内存使用,但不应该是一个问题,除非文件是巨大的,但也可以缩短执行时间。
答案 1 :(得分:0)
如果你实际上并不需要正则表达式而只是进行文字替换,那么string.replace()几乎肯定会更快。但即便如此,这里的瓶颈仍然是文件输入/输出,而不是字符串操作。
尽管最好的解决方案可能是使用cStringIO
答案 2 :(得分:0)
根据您正在操作的文本的相关与不相关部分的比例(以及每个替换的部分是否在重叠上运行),尝试分解输入可能更有效进入令牌并单独处理每个令牌。
由于当前实现中的每个replace()都必须检查整个输入字符串,因此速度很慢。如果您将该流分解为类似......
[<normal text>, <tag>, <tag>, <normal text>, <tag>, <normal text>]
# from an original "<normal text><tag><tag><normal text><tag><normal text>"
...然后您可以简单地查看给定的标记是否为标记,并将其替换为列表(最后是''.join()
)。
答案 3 :(得分:0)
您可以将函数对象传递给re.sub
而不是替换字符串,它会获取匹配对象并返回替换,例如
>>> r = re.compile(r'<(\w+)>|(-)')
>>> r.sub(lambda m: '(%s)' % (m.group(1) if m.group(1) else 'emdash'), '<atag>-<anothertag>')
'(atag)(emdash)(anothertag)'
当然你可以使用更复杂的函数对象,这个lambda只是一个例子。
使用执行所有替换的单个正则表达式应该比多次迭代字符串稍快一些,但是如果执行了大量替换,则调用计算替换的函数对象的开销可能很大。