如何搜索和替换文件中的文本?

Posted

技术标签:

【中文标题】如何搜索和替换文件中的文本?【英文标题】:How to search and replace text in a file? 【发布时间】:2013-06-13 00:22:06 【问题描述】:

如何使用 Python 3 搜索和替换文件中的文本?

这是我的代码:

import os
import sys
import fileinput

print ("Text to search for:")
textToSearch = input( "> " )

print ("Text to replace it with:")
textToReplace = input( "> " )

print ("File to perform Search-Replace on:")
fileToSearch  = input( "> " )
#fileToSearch = 'D:\dummy1.txt'

tempFile = open( fileToSearch, 'r+' )

for line in fileinput.input( fileToSearch ):
    if textToSearch in line :
        print('Match Found')
    else:
        print('Match Not Found!!')
    tempFile.write( line.replace( textToSearch, textToReplace ) )
tempFile.close()


input( '\n\n Press Enter to exit...' )

输入文件:

hi this is abcd hi this is abcd
This is dummy text file.
This is how search and replace works abcd

当我在上面的输入文件中搜索并用“abcd”替换“ram”时,它就像一个魅力。但是当我反之亦然,即用“ram”替换“abcd”时,最后会留下一些垃圾字符。

用“ram”替换“abcd”

hi this is ram hi this is ram
This is dummy text file.
This is how search and replace works rambcd

【问题讨论】:

你说“最后留下了一些垃圾字符”能不能再具体一点,你看到了什么? 用我得到的输出更新了问题。 edit text file using Python 这是实现map 而不是循环的好答案:***.com/questions/26986229/…,这就是我所采用的 【参考方案1】:

这个答案对我有用。以读取模式打开文件。以字符串格式读取文件。按预期替换文本。关闭文件。再次以写入模式打开文件。最后,将替换后的文本写入同一个文件。

    with open("file_name", "r+") as text_file:
        texts = text_file.read()
        texts = texts.replace("to_replace", "replace_string")
    with open(file_name, "w") as text_file:
        text_file.write(texts)
except FileNotFoundError as f:
    print("Could not find the file you are trying to read.")

【讨论】:

【参考方案2】:

我试过这个并使用 readlines 而不是 read

with open('dummy.txt','r') as file:
    list = file.readlines()
print(f'before removal list')
for i in list[:]:
        list.remove(i)

print(f'After removal list')
with open('dummy.txt','w+') as f:
    for i in list:
        f.write(i)

【讨论】:

【参考方案3】:

我遇到了同样的问题。问题是,当您在变量中加载 .txt 时,您将其用作字符串数组,而它是字符数组。

swapString = []
with open(filepath) as f: 
    s = f.read()
for each in s:
    swapString.append(str(each).replace('this','that'))
s = swapString
print(s)

【讨论】:

【参考方案4】:

我已经把它作为一个课程练习:打开文件,查找和替换字符串,然后写入一个新文件。

class Letter:

    def __init__(self):

        with open("./Input/Names/invited_names.txt", "r") as file:
            # read the list of names
            list_names = [line.rstrip() for line in file]
            with open("./Input/Letters/starting_letter.docx", "r") as f:
                # read letter
                file_source = f.read()
            for name in list_names:
                with open(f"./Output/ReadyToSend/LetterToname.docx", "w") as f:
                    # replace [name] with name of the list in the file
                    replace_string = file_source.replace('[name]', name)
                    # write to a new file
                    f.write(replace_string)


brief = Letter()

【讨论】:

【参考方案5】:

(pip install python-util)

from pyutil import filereplace

filereplace("somefile.txt","abcd","ram")

将所有出现的“abcd”替换为“ram”。 该函数还通过指定regex=True来支持正则表达式

from pyutil import filereplace

filereplace("somefile.txt","\\w+","ram",regex=True)

免责声明:我是作者 (https://github.com/MisterL2/python-util)

【讨论】:

我对此有一些不好的体验(它在文件末尾添加了一些字符),所以我不能推荐它,即使单行会很好。 @Azrael3000 它添加了字符?我还没有看到这种情况发生在我身上。如果您在 Github 上打开问题,我将不胜感激,以便我可以修复它github.com/MisterL2/python-util 感谢 github 问题!问题已解决,现在可以正常工作了。 您可以在答案中为您的图书馆添加一个赞吗? 我假设你的意思是“链接”? @SenhorLucas 添加了 github 的链接【参考方案6】:

除了已经提到的答案,这里解释了为什么最后会有一些随机字符: 您以r+ 模式打开文件,而不是w 模式。主要区别在于w 模式会在您打开文件后立即清除文件的内容,而r+ 不会。 这意味着如果你的文件内容是“123456789”并且你写“www”到它,你会得到“www456789”。它会用新输入覆盖字符,但保留任何剩余的输入不变。 您可以使用truncate(<startPosition>) 清除文件内容的一部分,但您最好先将更新的文件内容保存为字符串,然后执行truncate(0) 并一次将其全部写入。 或者你可以use my library:D

【讨论】:

【参考方案7】:

迟到的答案,但这是我用来在文本文件中查找和替换的内容:

with open("test.txt") as r:
  text = r.read().replace("THIS", "THAT")
with open("test.txt", "w") as w:
  w.write(text)

DEMO

【讨论】:

最好也做一个备份,以防万一发生任何错误。 @HomeroEsmeraldo 这几乎是常识,超出了这个答案的范围。【参考方案8】:

您也可以使用pathlib

from pathlib2 import Path
path = Path(file_to_search)
text = path.read_text()
text = text.replace(text_to_search, replacement_text)
path.write_text(text)

【讨论】:

谢谢悠亚。上述解决方案效果很好。注意:您需要先备份原始文件,因为它会替换您的原始文件本身。如果要重复替换文本,则可以继续添加最后 2 行,如下所示。 text = text.replace(text_to_search, replacement_text) path.write_text(text)【参考方案9】:

像这样:

def find_and_replace(file, word, replacement):
  with open(file, 'r+') as f:
    text = f.read()
    f.write(text.replace(word, replacement))

【讨论】:

请确保您的答案比该问题中已有的其他答案有所改进。 这会将带有替换的文本附加到文件的末尾,在我看来@Jack Aidley aswer 正是 OP 的意思***.com/a/17141572/6875391【参考方案10】:
def findReplace(find, replace):

    import os 

    src = os.path.join(os.getcwd(), os.pardir) 

    for path, dirs, files in os.walk(os.path.abspath(src)):

        for name in files: 

            if name.endswith('.py'): 

                filepath = os.path.join(path, name)

                with open(filepath) as f: 

                    s = f.read()

                s = s.replace(find, replace) 

                with open(filepath, "w") as f:

                    f.write(s) 

【讨论】:

【参考方案11】:

使用单个 with 块,您可以搜索和替换您的文本:

with open('file.txt','r+') as f:
    filedata = f.read()
    filedata = filedata.replace('abc','xyz')
    f.truncate(0)
    f.write(filedata)

【讨论】:

您在写入文件之前忘记seek 到文件的开头。 truncate 不这样做,所以文件中会有垃圾。【参考方案12】:

fileinput 已经支持就地编辑。在这种情况下,它将stdout 重定向到文件:

#!/usr/bin/env python3
import fileinput

with fileinput.FileInput(filename, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace(text_to_search, replacement_text), end='')

【讨论】:

end='' 参数应该做什么? line 已经有了换行符。 end 默认为换行符,end='' 使print() 函数不打印额外的换行符 不要使用文件输入!考虑自己编写代码来执行此操作。重定向 sys.stdout 不是一个好主意,特别是如果你没有尝试就这样做。最后就像 fileinput 一样。如果引发异常,您的标准输出可能永远无法恢复。 @craigds:错误。 fileinput 不是 所有 工作的工具(nothing 是)但在许多情况下它正确的工具,例如,实施Python 中的sed-like 过滤器。不要用螺丝刀敲钉子。 如果您真的出于某种原因想要将标准输出重定向到您的文件,那么做到这一点并不比fileinput 做得更好(基本上,使用try..finally 或contextmanager 以确保您之后将 stdout 设置回其原始值)。 fileinput 的源代码非常糟糕,它在后台做了一些非常不安全的事情。如果它是今天写的,我非常怀疑它是否会进入标准库。【参考方案13】:

正如 michaelb958 所指出的,您不能用不同长度的数据替换原位,因为这会使其余部分不合适。我不同意其他海报建议您从一个文件读取并写入另一个文件。相反,我会将文件读入内存,修复数据,然后在单独的步骤中将其写入同一个文件。

# Read in the file
with open('file.txt', 'r') as file :
  filedata = file.read()

# Replace the target string
filedata = filedata.replace('ram', 'abcd')

# Write the file out again
with open('file.txt', 'w') as file:
  file.write(filedata)

除非您要处理的文件太大而无法一次性加载到内存中,或者您担心在第二步将数据写入到文件。

【讨论】:

with file = open(..): 不是有效的 Python (=) 尽管意图很明确。 .replace() 不会修改字符串(它是不可变的),因此您需要使用返回的值。无论如何,支持大文件的代码can be even simpler 除非您需要搜索和替换跨多行的文本。 你说的很对,伙计们,这就是为什么你应该在互联网上让自己难堪之前测试你的代码;) @JonasStein:不,不应该。 with 语句在语句块末尾自动关闭文件。 @JackAidley 这很有趣。谢谢你的解释。 @JackAidley,因为它简短、简单、易于使用和理解,并解决了很多人遇到的一个实际问题(因此很多人都在搜索 - 从而找到你的答案)。 【参考方案14】:
def word_replace(filename,old,new):
    c=0
    with open(filename,'r+',encoding ='utf-8') as f:
        a=f.read()
        b=a.split()
        for i in range(0,len(b)):
            if b[i]==old:
                c=c+1
        old=old.center(len(old)+2)
        new=new.center(len(new)+2)
        d=a.replace(old,new,c)
        f.truncate(0)
        f.seek(0)
        f.write(d)
    print('All words have been replaced!!!')

【讨论】:

此代码将替换您想要的单词。唯一的问题是它重写了整个文件。如果文件太长而处理器无法处理,可能会卡住。【参考方案15】:

我稍微修改了 Jayram Singh 的帖子,以替换“!”的每个实例字符到我想随着每个实例递增的数字。认为这对于想要修改每行出现多次并想要迭代的角色可能会有所帮助。希望对某人有所帮助。 PS-如果我的帖子有任何不恰当之处,我很抱歉,但这对我有用。

f1 = open('file1.txt', 'r')
f2 = open('file2.txt', 'w')
n = 1  

# if word=='!'replace w/ [n] & increment n; else append same word to     
# file2

for line in f1:
    for word in line:
        if word == '!':
            f2.write(word.replace('!', f'[n]'))
            n += 1
        else:
            f2.write(word)
f1.close()
f2.close()

【讨论】:

【参考方案16】:

我已经这样做了:

#!/usr/bin/env python3

import fileinput
import os

Dir = input ("Source directory: ")
os.chdir(Dir)

Filelist = os.listdir()
print('File list: ',Filelist)

NomeFile = input ("Insert file name: ")

CarOr = input ("Text to search: ")

CarNew = input ("New text: ")

with fileinput.FileInput(NomeFile, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace(CarOr, CarNew), end='')

file.close ()

【讨论】:

伤心,但fileinput 不能与inplace=Trueutf-8 一起使用。【参考方案17】:

正如 Jack Aidley 所发布和 J.F. Sebastian 指出的那样,此代码将不起作用:

 # Read in the file
filedata = None
with file = open('file.txt', 'r') :
  filedata = file.read()

# Replace the target string
filedata.replace('ram', 'abcd')

# Write the file out again
with file = open('file.txt', 'w') :
  file.write(filedata)`

但是这段代码可以工作(我已经测试过了):

f = open(filein,'r')
filedata = f.read()
f.close()

newdata = filedata.replace("old data","new data")

f = open(fileout,'w')
f.write(newdata)
f.close()

使用这种方法,filein 和 fileout 可以是同一个文件,因为 Python 3.3 在打开写入时会覆盖文件。

【讨论】:

我相信区别就在这里:filedata.replace('ram', 'abcd') 相比:newdata = filedata.replace("old data","new data") 没关系"with" 语句 1.你为什么要删除with-statement? 2. 如我的回答所述,fileinput 可以就地工作——它可以替换同一文件中的数据(它在内部使用临时文件)。不同的是fileinput不需要将整个文件加载到内存中。 只是为了拯救其他人重新访问 Jack Aidley 的答案,自此答案以来已更正,因此此答案现在是多余的(并且由于丢失了更整洁的 with 块而劣势)。 不是很pythonic。我要么使用try/finally 来确保文件始终处于关闭状态,要么使用通常的with 语句,要么使用fileinput 选项。【参考方案18】:

我的变体,在整个文件中一次一个词。

我把它读入内存。

def replace_word(infile,old_word,new_word):
    if not os.path.isfile(infile):
        print ("Error on replace_word, not a regular file: "+infile)
        sys.exit(1)

    f1=open(infile,'r').read()
    f2=open(infile,'w')
    m=f1.replace(old_word,new_word)
    f2.write(m)

【讨论】:

【参考方案19】:

您的问题源于读取和写入同一个文件。与其打开fileToSearch 进行写入,不如打开一个实际的临时文件,然后在完成并关闭tempFile 后,使用os.rename 将新文件移到fileToSearch 上。

【讨论】:

友好的仅供参考(请随意编辑答案):根本原因是无法缩短文件的中间位置。即如果你搜索5个字符并替换为3,则搜索到的5个字符的前3个字符将被替换;但其他 2 个不能删除,它们只会留在那里。临时文件解决方案通过删除这些“剩余”字符而不是将它们写入临时文件来删除它们。【参考方案20】:

你可以这样替换

f1 = open('file1.txt', 'r')
f2 = open('file2.txt', 'w')
for line in f1:
    f2.write(line.replace('old_text', 'new_text'))
f1.close()
f2.close()

【讨论】:

以上是关于如何搜索和替换文件中的文本?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 中搜索和替换文件中的文本?

如何使用python搜索和替换DOTM文件中的字符串

Mac 和 Linux 上的文本文件中的递归搜索和替换

Python:如何替换pdf中的文本

如何使用C替换文本文件中的字符?

在文本文件中搜索和替换字符串