Optimization help needed: Search and Replace using dictionary of parameters

maxm maxm at mxm.dk
Wed Jan 2 13:49:52 CET 2002


"maxm" <maxm at mxm.dk> wrote ...

Well to do a followup to my own post ;-) I sort of needed the search and
replace functionality myself and so wrote a small script.

here goes...

###########################################################
# recursivley replaces ALL ocurrences of a string in files
# and optionally in the filenames too.

import re, string

class MultiReplace:

    def __init__(self, repl_dict):
        # "compile" replacement dictionary

        # assume char to char mapping
        charmap = map(chr, range(256))
        for k, v in repl_dict.items():
            if len(k) != 1 or len(v) != 1:
                self.charmap = None
                break
            charmap[ord(k)] = v
        else:
            self.charmap = string.join(charmap, "")
            return

        # string to string mapping; use a regular expression
        keys = repl_dict.keys()
        keys.sort() # lexical order
        pattern = string.join(map(re.escape, keys), "|")
        self.pattern = re.compile(pattern)
        self.dict = repl_dict


    def replace(self, str):
        # apply replacement dictionary to string
        if self.charmap:
            return string.translate(str, self.charmap)
        def repl(match, get=self.dict.get):
            item = match.group(0)
            return get(item, item)
        return self.pattern.sub(repl, str)



from os.path import walk, isdir, join, split
from os import rename

def getAllFiles(startDir):
    def visit(result, dirname, names):
        for file in names:
            result.append(join(dirname, file))
    result = []
    walk(startDir, visit, result)
    return result

def replace(startDir, mrDict, changeFileNames=0):
    # replaces ALL ocurrences of a string in both files and filenames
    mr = MultiReplace(mrDict)
    # search and replace in file content
    files = getAllFiles(startDir)
    for file in files:
         # Replace in files
        if not isdir(file):
            f = open(file, 'r+w')
            content = f.read()
            newContent = mr.replace(content)
            f.seek(0)
            f.write(newContent)
            f.truncate()
            f.close()
        #
        if changeFileNames == 1:
            # Rename filenames
            head, tail = split(file)
            newTail = mr.replace(tail)
            rename(file, join(head, newTail))

if __name__ == '__main__':
    startDir = 'C:/zope/zope243/lib/python/Products/ots_User/'
    replace(startDir, {'ots_emne_003':'ots_User'}, changeFileNames=1)





More information about the Python-list mailing list