在多个文件上查找和替换多个查询的最佳方法是什么?

时间:2011-08-09 07:07:31

标签: python regex performance search replace

我有一个以这种格式有超过200行的文件:

name old_id new_id

这个名称对我目前正在尝试做的事情毫无用处,但我仍然希望它在那里,因为它可能会对以后的调试有用。

现在,我需要遍历文件夹中的每个文件,找到old_id的所有实例,并用new_id替换它们。我正在扫描的文件是代码文件,可能长达数千行。我需要使用我拥有的200多个ID中的每一个来扫描每个文件,因为有些文件可以在多个文件中使用,而且每个文件可以多次使用。

这样做的最佳方法是什么?到目前为止,我一直在创建python脚本来弄清楚旧ID和新ID的列表以及哪些匹配相互匹配,但我一直在做非常低效,因为我基本上逐行扫描了第一个文件并获得了当前行的当前id,然后我将逐行扫描第二个文件,直到找到匹配。然后我再次为第一个文件中的每一行做了这个,最后我读了很多第二个文件。我不介意这样做效率低,因为它们是小文件。

现在我正在搜索可能有数千行代码的大约30-50个文件,我希望它更有效率。这只是一个爱好者项目,所以它不需要超级好,我只是不希望它花费超过5分钟来找到并替换所有内容,然后查看结果并看到我犯了一个小错误并需要重新做一遍。花几分钟就可以了(虽然我现在很确定他们可以用计算机做到这一点)但我只是不想让它变得荒谬。

那么最好的方法是什么呢?到目前为止,我一直在使用python,但它不需要是一个python脚本。我不关心代码中的优雅或者我做的任何事情,我只是想要一种简单的方法,使用最容易使用或实现的任何工具,用我的新ID替换所有旧的ID。

示例:

以下是ID列表中的一行。第一部分是名称,可以忽略,第二部分是旧的id,第三部分是需要替换旧id的新id。

unlock_music_play_grid_thumb_01 0x108043c 0x10804f0

以下是其中一个要替换的文件中的示例行:

const v1, 0x108043c

我需要能够用新的id替换id,所以看起来像这样:

const v1, 0x10804f0

1 个答案:

答案 0 :(得分:2)

mmap使用类似multiwordReplace的内容(我根据您的情况编辑了它)。

import os
import os.path
import re
from mmap import mmap
from contextlib import closing


id_filename = 'path/to/id/file'
directory_name = 'directory/to/replace/in'

# read the ids into a dictionary mapping old to new
with open(id_filename) as id_file:
    ids = dict(line.split()[1:] for line in id_file)    

# compile a regex to do the replacement
id_regex = re.compile('|'.join(map(re.escape, ids)))

def translate(match):
    return ids[match.group(0)]

def multiwordReplace(text):
    return id_regex.sub(translate, text)

for code_filename in os.listdir(directory_name):
    with open(os.path.join(directory, code_filename), 'r+') as code_file:
        with closing(mmap(code_file.fileno(), 0)) as code_map:
            new_file = multiword_replace(code_map)
    with open(os.path.join(directory, code_filename), 'w') as code_file:
        code_file.write(new_file)