【问题标题】:Delete line that contains a string in a txt file python在 txt 文件 python 中删除包含字符串的行
【发布时间】:2021-03-17 07:01:10
【问题描述】:

我正在尝试删除包含变量(电子邮件)的 txt 文件中的一行。

我想删除包含电子邮件的整行,例如mano@gmail.com 不仅仅是变量 到目前为止,这是我想出的,但它似乎不起作用。

with open("wappoint.txt.txt", "r") as w:
    lines = w.readlines()
with open("wappoint.txt.txt", "w") as w:
    for line in lines:
        if email.strip("\n") != email:
            w.write(line)

txt文件的内容是

vasv@gmail.com, 1
mano@gmail.com, 3

【问题讨论】:

  • 你的文件内容是什么?
  • @ppwater vasv@gmail.com, 1 mano@gmail.com, 3
  • 在数字之后是不同的行
  • 请将其发布到问题中。
  • 是的,我做错了

标签: python txt


【解决方案1】:

对此有许多注意事项:

  1. 如果您的文件很大,最好将其全部加载到内存中。
  2. 如果在处理过程中出现异常(甚至可能是KeyboardInterrruptException),通常希望保持原始文件不变(因此,我们将尝试使您的操作ACID)。
  3. 如果多个并发进程尝试修改您的文件,您需要一些保证,至少您的文件是安全的(也是 ACID)。
  4. 您可能(也可能不)需要备份文件。

有多种可能性(参见例如this SO question)。然而,根据我的经验,fileinput 的结果好坏参半:它可以很容易地修改一个或多个文件,可以选择为每个文件创建一个备份,但不幸的是它急切地在每个文件中写入(在遇到例外)。我在最后放了一个例子供参考。

我发现最简单和最安全的方法是使用临时文件(在与您正在处理的文件相同的目录中,并以唯一但可识别的方式命名),从srctmp, then mv tmp src 其中,至少出于实际目的,is atomic on most POSIX filesystems

def acceptall(line):
    return True

def filefilter(filename, filterfunc=acceptall, backup=None):
    if backup:
        backup = f'{filename}{backup}'  # leave None if no backup wanted
    tmpname = tempfile.mktemp(prefix=f'.{filename}-', dir=os.path.dirname(filename))
    with open(tmpname, 'w') as tmp, open(filename, 'r') as src:
        for line in src:
            if filterfunc(line):
                tmp.write(line)
    if backup:
        os.rename(filename, backup)
    os.rename(tmpname, filename)

您的案例示例:

filefilter('wappoint.txt.txt', lambda line: email not in line)

使用正则表达式排除多个电子邮件地址(不区分大小写且仅完全匹配),并生成.bak 备份文件:

matcher = re.compile(r'.*\b(bob|fred|jeff)@foo\.com\b', re.IGNORECASE)
filefilter(filename, lambda line: not matcher.match(line), backup='.bak')

我们还可以模拟如果在中间引发异常(例如在第一个匹配行)会发生什么:

def flaky(line):
    if email in line:
        1 / 0
    return True

filefilter(filename, flaky)

这将在第一个匹配行引发ZeroDivisionError。但是请注意在这种情况下您的文件根本没有被修改(并且没有进行备份)。作为副作用,临时文件仍然存在(这与其他实用程序一致,例如 rsync,在中断时将 .filename-<random> 不完整的临时文件留在目标位置)。


正如所承诺的,这里也是一个使用 fileinput 的示例,但有前面解释过的注意事项:

with fileinput.input(filename, inplace=True, backup='.bak') as f:
    for line in f:
        if email not in line:
            print(line, end='')  # this prints back to filename

【讨论】:

  • 该死的,这是很多信息。我使用的文件不大,所以我认为这会使事情变得过于复杂。我的文件最多只有 9 行。
  • 不过还是谢谢你,我相信有人会觉得这很有用
【解决方案2】:

你在找这个吗?:

with open("wappoint.txt", "r") as w:
    lines = w.readlines()
with open("wappoint.txt", "w") as w:
    for line in lines:
        if email not in line:
            w.write(line)

如果该行包含电子邮件,则会删除该行。

【讨论】:

  • 第一个效果很好,我试了第二个还是不行,谢谢!
  • @mmanol 好的,我很高兴它成功了!请点击复选标记接受此答案。
  • 这对于大于内存的文件会产生问题。此外,如果在写作过程中被中断(例如ctrl-C),它将破坏文件的其余部分。
  • 没错,但我的文件很小
【解决方案3】:

您似乎只想检查email 是否出现在line 中。

您的代码正在尝试进行(不)相等比较 - 当您应该检查子字符串时(即 email 是否出现在 line 中)。

一个合适的条件是:

if email not in line:

【讨论】:

    猜你喜欢
    • 2022-11-25
    • 2021-12-22
    • 2018-10-18
    • 2014-04-16
    • 2014-05-16
    • 2021-08-09
    • 2018-03-16
    • 2022-08-19
    相关资源
    最近更新 更多