Я не пробовал это на большом файле, чтобы увидеть, насколько он быстрый, но он должен быть довольно быстрым.
Чтобы использовать сценарий для удаления строк из конца файла:
./shorten.py 2 large_file.txt
Он ищет конец файла, проверяет, является ли последний символ новой строкой, затем читает каждый символ по одному, возвращаясь назад, пока не найдет три символа новой строки, и усекает файл сразу после этой точки. Изменение сделано на месте.
Изменить: я добавил версию Python 2.4 в нижней части.
Вот версия для Python 2.5 / 2.6:
#!/usr/bin/env python2.5 from __future__ import with_statement # also tested with Python 2.6 import os, sys if len(sys.argv) != 3: print sys.argv[0] + ": Invalid number of arguments." print "Usage: " + sys.argv[0] + " linecount filename" print "to remove linecount lines from the end of the file" exit(2) number = int(sys.argv[1]) file = sys.argv[2] count = 0 with open(file,'r+b') as f: f.seek(0, os.SEEK_END) end = f.tell() while f.tell() > 0: f.seek(-1, os.SEEK_CUR) char = f.read(1) if char != '\n' and f.tell() == end: print "No change: file does not end with a newline" exit(1) if char == '\n': count += 1 if count == number + 1: f.truncate() print "Removed " + str(number) + " lines from end of file" exit(0) f.seek(-1, os.SEEK_CUR) if count < number + 1: print "No change: requested removal would leave empty file" exit(3)
Вот версия Python 3:
#!/usr/bin/env python3.0 import os, sys if len(sys.argv) != 3: print(sys.argv[0] + ": Invalid number of arguments.") print ("Usage: " + sys.argv[0] + " linecount filename") print ("to remove linecount lines from the end of the file") exit(2) number = int(sys.argv[1]) file = sys.argv[2] count = 0 with open(file,'r+b', buffering=0) as f: f.seek(0, os.SEEK_END) end = f.tell() while f.tell() > 0: f.seek(-1, os.SEEK_CUR) print(f.tell()) char = f.read(1) if char != b'\n' and f.tell() == end: print ("No change: file does not end with a newline") exit(1) if char == b'\n': count += 1 if count == number + 1: f.truncate() print ("Removed " + str(number) + " lines from end of file") exit(0) f.seek(-1, os.SEEK_CUR) if count < number + 1: print("No change: requested removal would leave empty file") exit(3)
Вот версия Python 2.4:
#!/usr/bin/env python2.4 import sys if len(sys.argv) != 3: print sys.argv[0] + ": Invalid number of arguments." print "Usage: " + sys.argv[0] + " linecount filename" print "to remove linecount lines from the end of the file" sys.exit(2) number = int(sys.argv[1]) file = sys.argv[2] count = 0 SEEK_CUR = 1 SEEK_END = 2 f = open(file,'r+b') f.seek(0, SEEK_END) end = f.tell() while f.tell() > 0: f.seek(-1, SEEK_CUR) char = f.read(1) if char != '\n' and f.tell() == end: print "No change: file does not end with a newline" f.close() sys.exit(1) if char == '\n': count += 1 if count == number + 1: f.truncate() print "Removed " + str(number) + " lines from end of file" f.close() sys.exit(0) f.seek(-1, SEEK_CUR) if count < number + 1: print "No change: requested removal would leave empty file" f.close() sys.exit(3)