如何删除文本文件的第一行?

42

我一直在网上搜索,但没有找到任何好的解决方案。

这是我的文本文件:

[54, 95, 45, -97, -51, 84, 0, 32, -55, 14, 50, 54, 68, -3, 57, 88, -1]
[24, 28, 38, 37, 9, 44, -14, 84, -40, -92, 86, 94, 95, -62, 12, -36, -12]
[-26, -67, -89, -7, 12, -20, 76, 88, -15, 38, -89, -65, -53, -84, 31, -81, -91]
[-19, -50, 16, 47, -42, -31, 75, 0, 25, -95, 75, 97, 19, 77, -2, -31, -59]
[-66, -10, 35, -39, 24, 70, 74, -45, -27, 77, -44, 86, 57, 14, -91, -26, -20]
[-63, 80, -31, 70, 100, 22, -30, 74, 44, -35, -25, -75, -39, -13, -93, 0, 1]
[63, 13, 67, 55, -56, 45, 10, 61, -14, -55, 40, 84, -59, 7, 75, -64, -25]
[7, -50, -17, -86, -43, 34, 82, 84, 49, 18, 56, -31, -19, 59, -96, 72, -40]
[-73, 34, -68, 20, 30, 1, 49, 77, -94, 2, -83, 40, 2, 20, 66, 60, -36]
[-80, -12, 93, 77, 73, -55, 24, 3, -60, 12, -41, -43, -49, 36, 6, -93, -24]
[-41, 12, -43, 42, -70, 75, -84, -83, 30, 78, -3, 51, 69, 0, 65, 60, -15]
[82, 97, -57, -96, 25, -100, 61, 13, -80, -32, 99, 60, 58, -58, -45, -58, -53]
[-90, -34, 80, 95, -12, -34, 71, -83, 46, 10, -78, -40, 65, 53, -81, 40, -59]
[-80, -20, -87, -2, -54, 74, -79, 22, -20, 60, -84, -12, -40, -98, -81, -5, -35]
[33, 36, -46, 10, -77, 88, -99, -5, 19, -20, 89, 87, -47, 46, 10, 17, -67]
[-77, 73, 20, 44, 79, -14, -8, -49, 45, -49, -91, -21, 41, -13, 74, -71, -15]
[98, -99, 51, 53, 56, -78, 31, 45, 35, -36, -10, -86, 9, 94, 24, -2, -20]
[-37, 46, -77, -92, 48, -34, 75, 19, -74, -13, -100, 33, -46, 19, -60, 5, 5]
[-13, -30, -82, -70, 64, 87, 16, 67, -36, 22, -99, -92, 36, 8, 90, 48, -5]
[46, 75, -15, 24, 24, -37, -3, -45, 32, -84, -2, -16, 43, -88, 92, 27, -10]
我只想删除第一行(也就是使用第二行作为第一行,而不是在第一行填充空格)。请问有人能帮我吗?

3
你不应该使用Python来完成这个任务,而是可以使用bash命令:sed -i -e "1d" $FILE。 - WindowsMaker
5
也许Python不是最佳选择。一个简单的 tail -n +2 "$FILE" 就能达到效果,对吧? - Hyperboreus
19
如果用户想使用Python,那就让他用吧。在Python和其他编程语言中,都有快速实现的方法。 - Rushy Panchal
3
没问题。我只是想指出另一种方式,以防 OP 过于固定于 Python(我不了解 Python)。你知道的:「如果你所知道的唯一工具是锤子,那么所有问题都看起来像钉子。」 - Hyperboreus
1
@zaftcoAgeiha:可能需要在Python应用程序内部完成,就像我的情况一样,这也是我来这里的原因:)。我使用了从Python脚本中调用的“sed命令”来完成相同的操作,但我的代码审查人员不想为这么简单的事情生成一个新进程.....两者都有优缺点,例如在file.read()中,文件需要在内存中读取,对于大文件可能会有问题,但我需要先检查我的代码:) - ViFI
1
对于字符串而不是文件:https://dev59.com/rV0Z5IYBdhLWcg3w_0d8 - Ciro Santilli OurBigBook.com
9个回答

63

假设您有足够的内存来容纳所有内容:

with open('file.txt', 'r') as fin:
    data = fin.read().splitlines(True)
with open('file.txt', 'w') as fout:
    fout.writelines(data[1:])

我们可以更加高级一些,打开文件,读取后再回到开头,从而消除第二个open,但实际上,这已经足够好了。


3
使用head, tail = fin.read().split('\n', 1); ...; fout.write(tail) 可能更有效率。 (说明:这句话是在讨论文件操作中的一种方式,通过将读取的数据按行拆分成头和尾两个部分,然后只写入尾部部分来实现对文件的操作,并且认为这种方式更有效率。) - coldfix
@coldfix -- 是的,你可能是对的。虽然你可能会花费大部分时间坐在IO上,所以这可能并不会有太大的区别。 - mgilson
当您从多个线程使用文件或其他内容也在使用该文件时,这种方法并不安全。理论上,可以在不删除第一行的情况下进行读取。但是,在处理货币或其他重要数据时,这种方法并不安全,因为再次运行后,您将获得相同的行。 - DaWe
当然可以 -- 如果你希望用线程这样改变状态,它永远不会是线程安全的 -- 由你获得适当的锁来防止恶心的竞态条件或其他问题。 - mgilson
不需要两次打开文件 - 当您异步运行时,这是不安全的。您可能会丢失数据,因为您正在读取过时的内容,而更新后的字符串尚未写入文件中。更好的解决方案 - DaWe

15

这里有一个内存占用较少的 (?) 解决方案,它利用了shutil:

以下是需要翻译的内容:

import shutil

source_file = open('file.txt', 'r')
source_file.readline()
# this will truncate the file, so need to use a different file name:
target_file = open('file.txt.new', 'w')

shutil.copyfileobj(source_file, target_file)

不需要两次打开()文件-当您异步运行它时,这是不安全的。您可能会丢失数据,因为您正在读取过时的内容,而更新后的字符串尚未写入文件。更好的解决方案请参见:https://dev59.com/TGIj5IYBdhLWcg3wWT2c#60565865 - DaWe

9
你可以更轻松地完成它,只需简单地说明第一条要读的内容即可:
    with open(filename, "r") as f:
        rows = f.readlines()[1:]

7
更安全的做法是使用一个open()进行读写,这样如果你想从另一个线程/进程使用文件时不会丢失数据。
def pop(self, file):
    with open(file, 'r+') as f: # open file in read / write mode
        firstLine = f.readline() # read the first line and throw it out
        data = f.read() # read the rest
        f.seek(0) # set the cursor to the top of the file
        f.write(data) # write the data back
        f.truncate() # set the file size to the current size
        return firstLine

fifo = pop('filename.txt')

5

这个解决方案适用于不适合内存的大文件,它会一次读取和写入一行:

import os
from shutil import move
from tempfile import NamedTemporaryFile

# Take off the first line which has the system call and params
file_path = 'xxxx'
temp_path = None
with open(file_path, 'r') as f_in:
    with NamedTemporaryFile(mode='w', delete=False) as f_out:
        temp_path = f_out.name
        next(f_in)  # skip first line
        for line in f_in:
            f_out.write(line)

os.remove(file_path)
move(temp_path, file_path)

0
这是我用于从文件中删除第一行的代码 希望能对你有所帮助
  with open(r"dark.json", 'r+') as fp:
  # read an store all lines into list
  lines = fp.readlines()
  # move file pointer to the beginning of a file
  fp.seek(0)
  # truncate the file
  fp.truncate()

  # start writing lines except the first line
  # lines[1:] from line 2 to last line
  fp.writelines(lines[1:])

0

我也想要读取文件的第一行:

# open the file and read the contents
fp = open(file_path_name)
content = fp.readline()                 # read just the first line
print(content)

这个对我很有效。


0

Bash 对于此目的将更快。您可以在 Python 脚本中使用以下内容:

subprocess.Popen.communicate()

我编写了一个用于在 shell 中运行子进程 cmd 的函数:
def popen_method(call):
    subprocess_call = Popen([call], shell=True, stdout=PIPE, stderr=PIPE)
    out, err = subprocess_call.communicate()
    if err:
        raise yourError(
            '\n============= WARNING/ERROR ===============\n{}\n===========================================\n'.format(
                err.rstrip()))
    return out

你可以这样调用:

testing = "sed -i /var/output/ip_list.csv -e '1 s/^.*$/host_id,ip,last_updated/g'"
popen_method(testing)

或者使用:

from sh import sed

然后运行sed命令:

sed -i /var/output/ip_list.csv -e '1 s/^.*$/host_id,ip,last_updated/g'

这将用host_id,ip,last_updated替换您在第一行上的任何内容。


1
sed 的关键部分是:'1 s/^.*$/host_id,ip,last_updated/g',其中的 1 代表删除第一行(你也可以使用 sed "1d"),s/^.$/wtv here.../g 将替换从开头行符号 ^ 到结尾行符号 $ 的所有内容为 "wtv here...",g=全局替换。 - sweluhu

0

仅是一个建议,因为我遇到了同样的问题,但我不想删除原始 .txt 文件中的第一行,只是想使用第二行及其后面的内容。

我使用了简单的解决方案:

with open(file) as f:
    content = f.readlines()
    content = content[1:]

如果你不想永久删除文件内容,这通常是适用的情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接