我该如何在一个大小为3GB的文本文件中获取某一行?所有行的长度都相同,且用
\n
作为分隔符。我需要能够按需获取任何一行。请问应该如何操作?只需要返回一行即可。\n
作为分隔符。我需要能够按需获取任何一行。请问应该如何操作?只需要返回一行即可。dd(1)
并给它一个跳过参数。$ dd if=filename bs=<line-length> skip=<line_no - 1> count=1 2>/dev/null
这个想法是通过跳过之前的所有行 (skip=<line_no - 1>
) 并读取一行 (count=1
)。因为块大小设置为行长度 (bs=<line-length>
),所以每个块实际上就是一行。将stderr重定向,这样你就不会在结尾得到烦人的统计信息。
这比通过一个程序流式传输所需行之前的所有行,然后将它们全部丢弃更有效,因为dd
会跳转到文件中想要的位置并从文件中读取一行数据。
head -10 file | tail -1
返回文件的第10行,但速度可能较慢。
来源:这里
# print line number 52
sed -n '52p' # method 1
sed '52!d' # method 2
sed '52q;d' # method 3, efficient on large files
awk 'NR == 3 {print; exit}' file.txt
head -n N filespec | tail -1
其中N
是您想要的行号。
不幸的是,对于一个3GB的文件,这不会是最佳性能的代码,但有办法让它变得更好。
如果文件变化不太频繁,您可能需要考虑对其进行索引。我的意思是有另一个文件,其中包含定长记录的行偏移量。
因此,该文件为:
0000000000
0000000017
0000000092
0000001023
0000000092
,会给您在主文件中使用的偏移量。有了这个额外的信息,您不需要索引 - 您可以通过将记录长度乘以记录长度立即定位到主文件中的正确位置(假设值适合您的数据类型)。更新:如果重要的话,所有行都具有相同的长度。
def getline(fhandle,reclen,recnum):
seek to position reclen*recnum for file fhandle.
read reclen characters into buffer.
return buffer.
sed
和q
一起来使搜索在打印出该行后停止。sed -n '11723{p;q}' filename
Python (仅具有最小错误检查):
#!/usr/bin/env python
import sys
# by Dennis Williamson - 2010-05-08
# for https://dev59.com/bHE85IYBdhLWcg3wZyqt
# seeks the requested line in a file with a fixed line length
# Usage: ./lineseek.py LINE FILE
# Example: ./lineseek 11723 data.txt
EXIT_SUCCESS = 0
EXIT_NOT_FOUND = 1
EXIT_OPT_ERR = 2
EXIT_FILE_ERR = 3
EXIT_DATA_ERR = 4
# could use a try block here
seekline = int(sys.argv[1])
file = sys.argv[2]
try:
if file == '-':
handle = sys.stdin
size = 0
else:
handle = open(file,'r')
except IOError as e:
print >> sys.stderr, ("File Open Error")
exit(EXIT_FILE_ERR)
try:
line = handle.readline()
lineend = handle.tell()
linelen = len(line)
except IOError as e:
print >> sys.stderr, ("File I/O Error")
exit(EXIT_FILE_ERR)
# it would be really weird if this happened
if lineend != linelen:
print >> sys.stderr, ("Line length inconsistent")
exit(EXIT_DATA_ERR)
handle.seek(linelen * (seekline - 1))
try:
line = handle.readline()
except IOError as e:
print >> sys.stderr, ("File I/O Error")
exit(EXIT_FILE_ERR)
if len(line) != linelen:
print >> sys.stderr, ("Line length inconsistent")
exit(EXIT_DATA_ERR)
print(line)
参数验证应该更好,还有许多其他改进的空间。
$ perl -ne 'if (YOURLINENUMBER..YOURLINENUMBER) {print $_; last;}' /path/to/your/file