如何在文件中搜索字符串并将其替换为Python中的多行?

时间:2016-03-18 02:00:14

标签: python python-3.x file-io replace multiline

我正在运行Python 3.5.1

我有一个文本文件,我试图搜索并替换或覆盖文本,如果它与预定义的变量匹配。以下是一个简单的例子:

test2.txt

A Bunch of Nonsense Stuff
############################
# More Stuff Goes HERE     #
############################
More stuff here
Outdated line of information that has no comment above - message_label

此示例中的最后一行需要被覆盖,因此新文件如下所示:

脚本

test2.txt

A Bunch of Nonsense Stuff
############################
# More Stuff Goes HERE     #
############################
More stuff here

# This is an important line that needs to be copied
Very Important Line of information that the above line is a comment for - message_label

我编写的函数 idealAppend 无法按预期工作,后续执行会造成一些混乱。我的解决方法是将两行分成单行变量,但这不能很好地扩展。我希望在我的脚本中使用此功能,能够处理任意数量的行。 (如果这是有道理的)

脚本

#!/usr/bin/env python3
import sys, fileinput, os
def main():

    file = 'test2.txt'
    fullData = r'''
# This is an important line that needs to be copied
Very Important Line of information that the above line is a comment for - message_label
'''
    idealAppend(file, fullData)


def idealAppend(filename, data):
    label = data.split()[-1]                                            # Grab last word of the Append String
    for line in fileinput.input(filename, inplace=1, backup='.bak'):
        if line.strip().endswith(label) and line != data:               # If a line 2 exists that matches the last word (label)
            line = data                                                 # Overwrite with new line, comment, new line, and append data.
        sys.stdout.write(line)                                          # Write changes to current line

    with open(filename, 'r+') as file:                                  # Open File with rw permissions
        line_found = any(data in line for line in file)                 # Search if Append exists in file

        if not line_found:                                              # If data does NOT exist
            file.seek(0, os.SEEK_END)                                   # Goes to last line of the file
            file.write(data)                                            # Write data to the end of the file


if __name__ == "__main__": main()

变通办法脚本
只要我只需要写两行就可以完美地工作。我喜欢这个在线数方面更具动感,所以我可以轻松地重复使用这个功能。

#!/usr/bin/env python3
import sys, fileinput, os
def main():

    file = 'test2.txt'
    comment = r'# This is an important line that needs to be copied'
    append = r'Very Important Line of information that the above line is a comment for - message_label'

    appendFile(file, comment, append)

def appendFile(filename, comment, append):

    label = append.split()[-1]                                          # Grab last word of the Append String
    for line in fileinput.input(filename, inplace=1, backup='.bak'):
        if line.strip().endswith(label) and line != append:             # If a line 2 exists that matches the last word (label)
            line = '\n' + comment + '\n' + append                       # Overwrite with new line, comment, new line, and append data.
        sys.stdout.write(line)                                          # Write changes to current line

    with open(filename, 'r+') as file:                                  # Open File with rw permissions
        line_found = any(append in line for line in file)               # Search if Append exists in file

        if not line_found:                                              # If data does NOT exist
            file.seek(0, os.SEEK_END)                                   # Goes to last line of the file
            file.write('\n' + comment + '\n' + append)                  # Write data to the end of the file

if __name__ == "__main__": main()

我是Python的新手,所以我希望有一个我忽略的简单解决方案。我认为尝试将新行字符中的 fullData 变量拆分为列表或元组,从列表中的最后一项过滤标签,然后输出所有条目但这已经开始超越我迄今为止学到的东西。

3 个答案:

答案 0 :(得分:1)

如果我正确理解您的问题,您只需打开输入和输出文件,然后检查该行是否包含旧信息,并以标签结束并相应地写入相应的内容。

with open('in.txt') as f, open('out.txt', 'r') as output:
    for line in f:
        if line.endswith(label) and not line.startswith(new_info):
            output.write(replacement_text)
        else:
            output.write(line)

如果您想更新原始文件而不是创建第二个文件,最简单的方法是删除原始文件并重命名新文件而不是尝试修改原文件。

答案 1 :(得分:0)

这是你在找什么?它正在寻找一个标签,然后用你想要的任何东西替换整条线。

<强>的test2.txt

A Bunch of Nonsense Stuff
############################
# More Stuff Goes HERE     #
############################
More stuff here

Here is to be replaced - to_replace

<强> script.py

#!/usr/bin/env python3

def main():
    file = 'test2.txt'
    label_to_modify = "to_replace"
    replace_with = "# Blabla\nMultiline\nHello"
    """
    # Raw string stored in a file
    file_replace_with = 'replace_with.txt'
    with open(file_replace_with, 'r') as f:
        replace_with = f.read()
    """
    appendFile(file, label_to_modify, replace_with)

def appendFile(filename, label_to_modify, replace_with):
    new_file = []
    with open(filename, 'r') as f:
        for line in f:
            if len(line.split()) > 0 and line.split()[-1] == label_to_modify:
                new_file.append(replace_with)
            else:
                new_file.append(line)

    with open(filename + ".bak", 'w') as f:
        f.write(''.join(new_file))

if __name__ == "__main__": main()

<强> test2.txt.bak

A Bunch of Nonsense Stuff
############################
# More Stuff Goes HERE     #
############################
More stuff here

# Blabla
Multiline
Hello

答案 2 :(得分:0)

阅读这两个答案我已经提出以下作为我可以开始工作的最佳解决方案。它似乎做了我需要的一切。谢谢大家。

#!/usr/bin/env python3

def main():

    testConfFile = 'test2.txt' # /etc/apache2/apache2.conf
    testConfLabel = 'timed_combined'
    testConfData = r'''###This is an important line that needs to be copied - ##-#-####
Very Important Line of information that the above line is a \"r\" comment for - message_label'''

    testFormatAppend(testConfFile, testConfData, testConfLabel)     # Add new test format

def testFormatAppend(filename, data, label):
    dataSplit = data.splitlines()
    fileDataStr = ''

    with open(filename, 'r') as file:
        fileData = stringToDictByLine(file)

    for key, val in fileData.items():
        for row in dataSplit:
            if val.strip().endswith(row.strip().split()[-1]):
                fileData[key] = ''

    fileLen = len(fileData) 
    if fileData[fileLen] == '':
        fileLen += 1
        fileData[fileLen] = data
    else:
        fileLen += 1
        fileData[fileLen] = '\n' + data

    for key, val in fileData.items():
        fileDataStr += val

    with open(filename, 'w') as file:
        file.writelines(str(fileDataStr))


def stringToDictByLine(data):
    fileData = {}
    i = 1
    for line in data:
        fileData[i] = line
        i += 1
    return fileData

if __name__ == "__main__": main()