用Python替换文件中的字符串 [英] Replace strings in files by Python

查看:928
本文介绍了用Python替换文件中的字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在给定目录及其子目录中以递归方式替换匹配项?

import os
import re
from os.path import walk
for root, dirs, files in os.walk("/home/noa/Desktop/codes"):
        for name in dirs:
                re.search("dbname=noa user=noa", "dbname=masi user=masi")
                   // I am trying to replace here a given match in a file

推荐答案

将所有这些代码放入名为mass_replace的文件中.在Linux或Mac OS X下,您可以执行chmod +x mass_replace,然后运行它.在Windows下,您可以使用python mass_replace后面加上适当的参数来运行它.

Put all this code into a file called mass_replace. Under Linux or Mac OS X, you can do chmod +x mass_replace and then just run this. Under Windows, you can run it with python mass_replace followed by the appropriate arguments.

#!/usr/bin/python

import os
import re
import sys

# list of extensions to replace
DEFAULT_REPLACE_EXTENSIONS = None
# example: uncomment next line to only replace *.c, *.h, and/or *.txt
# DEFAULT_REPLACE_EXTENSIONS = (".c", ".h", ".txt")

def try_to_replace(fname, replace_extensions=DEFAULT_REPLACE_EXTENSIONS):
    if replace_extensions:
        return fname.lower().endswith(replace_extensions)
    return True


def file_replace(fname, pat, s_after):
    # first, see if the pattern is even in the file.
    with open(fname) as f:
        if not any(re.search(pat, line) for line in f):
            return # pattern does not occur in file so we are done.

    # pattern is in the file, so perform replace operation.
    with open(fname) as f:
        out_fname = fname + ".tmp"
        out = open(out_fname, "w")
        for line in f:
            out.write(re.sub(pat, s_after, line))
        out.close()
        os.rename(out_fname, fname)


def mass_replace(dir_name, s_before, s_after, replace_extensions=DEFAULT_REPLACE_EXTENSIONS):
    pat = re.compile(s_before)
    for dirpath, dirnames, filenames in os.walk(dir_name):
        for fname in filenames:
            if try_to_replace(fname, replace_extensions):
                fullname = os.path.join(dirpath, fname)
                file_replace(fullname, pat, s_after)

if len(sys.argv) != 4:
    u = "Usage: mass_replace <dir_name> <string_before> <string_after>\n"
    sys.stderr.write(u)
    sys.exit(1)

mass_replace(sys.argv[1], sys.argv[2], sys.argv[3])

我已经从原始答案更改了上面的代码.有几个变化.首先,mass_replace()现在调用re.compile()来预编译搜索模式;其次,要检查文件的扩展名,我们现在将文件扩展名的元组传递给.endswith(),而不是调用.endswith()三次.第三,它现在使用最新版本的Python中可用的with语句;最后,file_replace()现在检查以查看是否在文件中找到了模式,如果未找到模式,则不重写文件. (旧版本将重写每个文件,即使输出文件与输入文件相同,也将更改时间戳;这不雅致.)

I have changed the above code from the original answer. There are several changes. First, mass_replace() now calls re.compile() to pre-compile the search pattern; second, to check what extension the file has, we now pass in a tuple of file extensions to .endswith() rather than calling .endswith() three times; third, it now uses the with statement available in recent versions of Python; and finally, file_replace() now checks to see if the pattern is found within the file, and doesn't rewrite the file if the pattern is not found. (The old version would rewrite every file, changing the timestamps even if the output file was identical to the input file; this was inelegant.)

我将其默认更改为替换每个文件,但是您可以编辑一行以将其限制为特定的扩展名.我认为替换每个文件是一个更有用的现成默认值.可以使用一系列扩展名或不可触摸的文件名,使其不区分大小写的选项等扩展.

I changed this to default to replacing every file, but with one line you can edit to limit it to particular extensions. I think replacing every file is a more useful out-of-the-box default. This could be extended with a list of extensions or filenames not to touch, options to make it case insensitive, etc.

在评论中,@ asciimo指出了一个错误.我对此进行了修改,以修复该错误.记录str.endswith()可以接受要尝试的字符串元组,但不能接受列表.固定的.另外,我使几个函数接受一个可选参数,以使您可以传入一个扩展元组.修改它以接受命令行参数来指定哪些扩展名应该很容易.

In a comment, @asciimo pointed out a bug. I edited this to fix the bug. str.endswith() is documented to accept a tuple of strings to try, but not a list. Fixed. Also, I made a couple of the functions accept an optional argument to let you pass in a tuple of extensions; it should be pretty easy to modify this to accept a command-line argument to specify which extensions.

这篇关于用Python替换文件中的字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆