Rus*_*rry 31 linux sed text-manipulation
我有一个非常大的文件(~400 GB),我需要从中删除最后两行。我尝试使用sed,但在我放弃之前它运行了几个小时。有没有一种快速的方法可以做到这一点,还是我坚持sed?
Den*_*son 31
我还没有在大文件上试过这个,看看它有多快,但它应该相当快。
要使用脚本从文件末尾删除行:
./shorten.py 2 large_file.txt
Run Code Online (Sandbox Code Playgroud)
它寻找到文件的末尾,检查以确保最后一个字符是换行符,然后一次一个地读取每个字符,直到找到三个换行符并在该点之后截断文件。更改已就位。
编辑:我在底部添加了一个 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)
Run Code Online (Sandbox Code Playgroud)
这是一个 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)
Run Code Online (Sandbox Code Playgroud)
这是一个 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)
Run Code Online (Sandbox Code Playgroud)
use*_*894 12
你可以试试 GNU head
head -n -2 file
Run Code Online (Sandbox Code Playgroud)
我看到我的 Debian Squeeze/测试系统(但不是 Lenny/stable)包含一个“truncate”命令作为“coreutils”包的一部分。
有了它,你可以简单地做类似的事情
truncate --size=-160 myfile
Run Code Online (Sandbox Code Playgroud)
从文件末尾删除 160 个字节(显然你需要弄清楚你需要删除多少个字符)。
sed 的问题在于它是一个流编辑器——即使您只想在接近尾声时进行修改,它也会处理整个文件。因此,无论如何,您都是在逐行创建一个新的 400GB 文件。任何对整个文件进行操作的编辑器都可能有这个问题。
如果您知道行数,则可以使用head,但这同样会创建一个新文件,而不是更改现有文件。我猜您可能会从操作的简单性中获得速度提升。
您可能会更幸运地使用split将文件分成更小的部分,编辑最后一个,然后cat再次组合它们,但我不确定它是否会更好。我会使用字节数而不是行数,否则它可能根本不会更快——您仍将创建一个新的 400GB 文件。