使用Python删除文件中的特定行

Sou*_*urD 127 python file input

假设我有一个充满昵称的文本文件.如何使用Python从此文件中删除特定昵称?

hou*_*oft 176

假设您的文件的格式为每行一个昵称,请使用此方法.

首先,打开文件:

with open("yourfile.txt", "r") as f:
    lines = f.readlines()
with open("yourfile.txt", "w") as f:
    for line in lines:
        if line.strip("\n") != "nickname_to_delete":
            f.write(line)
Run Code Online (Sandbox Code Playgroud)

接下来,从文件中获取所有行:

with open("yourfile.txt", "r") as f:
    lines = f.readlines()
with open("yourfile.txt", "w") as f:
    for line in lines:
        if line.strip("\n") != "nickname_to_delete":
            f.write(line)
Run Code Online (Sandbox Code Playgroud)

现在您可以关闭文件:

with open("yourfile.txt", "r") as f:
    lines = f.readlines()
with open("yourfile.txt", "w") as f:
    for line in lines:
        if line.strip("\n") != "nickname_to_delete":
            f.write(line)
Run Code Online (Sandbox Code Playgroud)

并在写入模式下重新打开它:

with open("yourfile.txt", "r") as f:
    lines = f.readlines()
with open("yourfile.txt", "w") as f:
    for line in lines:
        if line.strip("\n") != "nickname_to_delete":
            f.write(line)
Run Code Online (Sandbox Code Playgroud)

然后,写回您的行,但要删除的行除外.您可能希望将更strip("\n")改为结束文件使用的任何行.

with open("yourfile.txt", "r") as f:
    lines = f.readlines()
with open("yourfile.txt", "w") as f:
    for line in lines:
        if line.strip("\n") != "nickname_to_delete":
            f.write(line)
Run Code Online (Sandbox Code Playgroud)

最后,再次关闭文件.

with open("yourfile.txt", "r") as f:
    lines = f.readlines()
with open("yourfile.txt", "w") as f:
    for line in lines:
        if line.strip("\n") != "nickname_to_delete":
            f.write(line)
Run Code Online (Sandbox Code Playgroud)

  • @Ooker,当你读取一条线时,试着想象一下光线在读取时沿着线移动.一旦读取该行,光标就会超过它.当您尝试写入文件时,您将写入光标当前所在的位置.通过重新打开文件,您可以重置光标. (5认同)
  • 使用含有化合物! (4认同)
  • @Ooker:您必须打开文件两次(并在两者之间关闭它),因为在第一种模式下它是"只读",因为您只是读取文件中的当前行.然后关闭它并在"写入模式"下重新打开它,在该模式下文件是可写的,并且替换文件的内容而不是要删除的行. (3认同)
  • 为什么我们要打开和关闭它两次? (2认同)
  • 为什么Python不允许我们在一行中执行此操作? (2认同)
  • 该任务只能完成一次打开文件的操作……但是需要将其打开为“ r +”,并且AND,您需要调用flie.seek(0)(将光标移至开头)和file.truncate ()(使现有内容无效),然后再将其重写。 (2认同)

Lot*_*her 84

只需一次打开即可解决此问题:

with open("target.txt", "r+") as f:
    d = f.readlines()
    f.seek(0)
    for i in d:
        if i != "line you want to remove...":
            f.write(i)
    f.truncate()
Run Code Online (Sandbox Code Playgroud)

此解决方案以r/w模式("r +")打开文件,并使用seek重置f指针,然后截断以删除最后一次写入后的所有内容.

  • 我不会的 如果您在`for`循环中遇到错误,您将最终得到部分覆盖的文件,其中重复的行或行的一半被截断。您可能想在f.seek(0)之后紧跟着f.truncate()。这样,如果遇到错误,您将最终得到不完整的文件。但是真正的解决方案(如果有磁盘空间)是输出到一个临时文件,然后使用os.replace()或pathlib.Path(temp_filename).replace(original_filename)将其与原始文件交换。一切都成功了。 (3认同)
  • 这对我来说非常好用,因为我还必须使用lockfile(fcntl).我找不到任何方法将fileinput与fcntl一起使用. (2认同)

Bar*_*abe 23

最好和最快的选择,而不是将所有内容存储在列表中并重新打开文件来编写它,我认为在其他地方重写文件.

with open("yourfile.txt", "r") as input:
    with open("newfile.txt", "w") as output: 
        for line in input:
            if line.strip("\n") != "nickname_to_delete":
                output.write(line)
Run Code Online (Sandbox Code Playgroud)

而已!在一个循环和一个循环只有你可以做同样的事情.它会快得多.

  • `os.replace`(python v 3.3中的新增内容)比系统调用`mv`更具跨平台性. (5认同)
  • @ShriShinde在循环文件对象时,你没有将文件读入内存,所以这个解决方案与你的建议完全相同. (4认同)

iva*_*ncz 20

这是来自@Lother答案的"分叉" (我认为这应该被认为是正确的答案).


对于这样的文件:

$ cat file.txt 
1: october rust
2: november rain
3: december snow
Run Code Online (Sandbox Code Playgroud)

来自Lother的解决方案的这个分支工作正常:

#!/usr/bin/python3.4

with open("file.txt","r+") as f:
    new_f = f.readlines()
    f.seek(0)
    for line in new_f:
        if "snow" not in line:
            f.write(line)
    f.truncate()
Run Code Online (Sandbox Code Playgroud)

改进:

  • with open,放弃使用 f.close()
  • 更清楚地if/else评估当前行中是否存在字符串


Kin*_*ngz 7

在第一遍中读取行并在第二遍中进行更改(删除特定行)的问题在于,如果文件大小很大,则会耗尽 RAM。相反,更好的方法是逐行读取行,然后将它们写入单独的文件中,删除不需要的行。我已经对 12-50 GB 的文件运行了这种方法,并且 RAM 使用率几乎保持不变。只有 CPU 周期显示正在进行的处理。


s4m*_*0o1 6

尚未提出一个简单的解决方案:

with open( file_of_nicknames, "r+" ) as f:
    lines = f.readlines()           # Get a list of all lines
    f.seek(0)                       # Reset the file to the beginning

    idx = lines.index("Nickname\n") # Don't forget the '\n'
    lines.pop( idx )                # Remove the corresponding index

    f.truncate()                    # Stop processing now
                                    # because len(file_lines) > len( lines ) 
    f.writelines( lines )           # write back
Run Code Online (Sandbox Code Playgroud)

受到先例答案的启发