【问题标题】:How to find and replace multiple lines in text file?如何查找和替换文本文件中的多行?
【发布时间】:2014-03-05 10:15:46
【问题描述】:

我正在运行 Python 2.7。

我有三个文本文件:data.txtfind.txtreplace.txt。现在,find.txt 包含我想在data.txt 中搜索的几行,并将该部分替换为replace.txt 中的内容。这是一个简单的例子:

data.txt

pumpkin
apple
banana
cherry
himalaya
skeleton
apple
banana
cherry
watermelon
fruit

find.txt

apple
banana
cherry

replace.txt

1
2
3

因此,在上面的示例中,我想在数据中搜索所有出现的applebananacherry,并将这些行替换为1,2,3

由于我的data.txt 大约为 1MB,所以我在正确的方法上遇到了一些麻烦,所以我希望尽可能高效。一种愚蠢的方法是将所有内容连接成一个长字符串并使用replace,然后输出到一个新的文本文件,以便恢复所有换行符。

import re

data = open("data.txt", 'r')
find = open("find.txt", 'r')
replace = open("replace.txt", 'r')

data_str = ""
find_str = ""
replace_str = "" 

for line in data: # concatenate it into one long string
    data_str += line

for line in find: # concatenate it into one long string
    find_str += line

for line in replace: 
    replace_str += line


new_data = data_str.replace(find, replace)
new_file = open("new_data.txt", "w")
new_file.write(new_data)

但是对于像我这样的大型数据文件来说,这似乎太复杂且效率低下。此外,replace 函数似乎已被弃用,因此不太好。

另一种方法是逐行遍历并跟踪您找到匹配的行。

类似这样的:

location = 0

LOOP1: 
for find_line in find:
    for i, data_line in enumerate(data).startingAtLine(location):
        if find_line == data_line:
            location = i # found possibility

for idx in range(NUMBER_LINES_IN_FIND):
    if find_line[idx] != data_line[idx+location]  # compare line by line
        #if the subsequent lines don't match, then go back and search again
        goto LOOP1

我知道,代码不完整。我什至不知道是否可以从某行上或某些行之间的某行搜索文件,但同样,我对这一切的逻辑有点困惑。做这个的最好方式是什么?

谢谢!

【问题讨论】:

    标签: python string file replace


    【解决方案1】:

    如果文件很大,你想readwrite 一次一行,所以整个东西不会一次加载到内存中。

    # create a dict of find keys and replace values
    findlines = open('find.txt').read().split('\n')
    replacelines = open('replace.txt').read().split('\n')
    find_replace = dict(zip(findlines, replacelines))
    
    with open('data.txt') as data:
        with open('new_data.txt', 'w') as new_data:
            for line in data:
                for key in find_replace:
                    if key in line:
                        line = line.replace(key, find_replace[key])
                new_data.write(line)
    

    编辑:我将代码更改为 read().split('\n') 而不是 readliens(),因此 \n 不包含在查找和替换字符串中

    【讨论】:

    • 谢谢你!现在,我忘记在我的问题中明确包含另一个问题,我担心这可能会产生误导。如果replace.txt 包含的行数多于find.txt,则zip 函数将忽略这些多余的行。现在,我仍然希望将它们包含在内,所以我希望将那个插槽替换为 1,2,3,4,5,而不是 apple,banana,cherry 替换为 1,2,3。这可能吗?
    • 您想要替换 what 插槽?没有钥匙,就没有什么可以代替的
    • 是的,我明白你在说什么,但我的意思是:在我的数据中,我希望能够将find.txt 文件apple,banana,cherry 中确定的行替换为任何行数。因此,如果replace.txtfind.txt 多10 行,它仍然会将它们插入数据中,从而使数据列表更长。或者replace.txt 可能比find.txt 更短。我希望我说得通。基本上,就我的使用而言,我不能假设replace.txt 的行数与find.txt 相同
    • 您可能应该将其作为一个全新的问题提出。和这个有本质的区别,评论的形式也不清楚
    • 没问题。如果您提出的问题得到满意回答,请不要忘记accept an answer
    【解决方案2】:

    这里有几件事:

    replace 未被弃用,详情请参阅此讨论: Python 2.7: replace method of string object deprecated

    如果您担心一次将 data.txt 全部读入内存,您应该能够一次遍历 data.txt 一行

    data = open("data.txt", 'r')
    for line in data:
        # fix the line
    

    所以剩下的就是提出一大堆查找/替换对并修复每一行。查看zip 函数,了解一种方便的方法

    find = open("find.txt", 'r').readlines()
    replace = open("replace.txt", 'r').readlines()
    new_data = open("new_data.txt", 'w')
    for find_token, replace_token in zip(find, replace):
        new_line = line.replace(find_token, replace_token)
        new_data.write(new_line + os.linesep)
    

    【讨论】:

    • +1 用于纠正我对字符串模块 replace 弃用而不是字符串类型 replace 弃用的错误混淆。因此,replace 并未被弃用。那很好!谢谢。
    猜你喜欢
    • 2017-06-28
    • 2011-07-29
    • 2012-11-10
    • 1970-01-01
    • 2011-08-11
    • 2013-01-29
    • 2014-08-22
    相关资源
    最近更新 更多