2010-05-08 82 views

回答

18

如果所有的線具有相同的長度,目前最好的辦法,是用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將尋求文件中您想要的位置並只讀取一行來自文件的數據。

+0

+1。基本上和我之後的解決方案一樣,在額外的固定記錄大小片段被添加到問題後,但具有不需要編寫自己的程序的明顯優勢。 – paxdiablo 2010-05-08 12:54:19

+1

這太書呆子了。嘿。 dd,我喜歡它。 – JavaRocky 2010-05-08 13:00:08

3

如果它不是一個固定的記錄長度的文件,你不這樣做某種形式就行了索引的開始,最好的辦法是隻使用:

head -n N filespec | tail -1 

其中N是行號你要。

不幸的是,這不會成爲3Gb文件的性能最佳的一段代碼,但有辦法使它更好。

如果文件沒有經常更改,您可能需要考慮將其編入索引。我的意思是讓另一個文件中的行偏移量作爲固定長度的記錄。

所以文件:

0000000000 
0000000017 
0000000092 
0000001023 

會給你一個快速的方法來查找每一行。只需將索引記錄大小乘以所需的行號,然後在索引文件中尋找。

然後使用該位置的值在主文件中查找,以便您可以讀取直到下一個換行符。

因此,對於第3行,您會在索引文件中找到33(索引記錄長度爲10個字符,再加上一個換行符)。讀取那裏的值,0000000092,會給你用在主文件中的偏移量。

當然,如果文件頻繁更改,這並不是很有用,但如果您可以控制事件追加時發生的情況,您仍然可以高效地向索引添加偏移量。如果你的不是,那麼只要索引的最後修改日期早於主文件的索引,就必須重新索引。


,並根據您的更新:

更新:如果它的事項,所有的線具有相同的長度。

有了這些額外的信息,您不需要索引 - 您可以通過將記錄長度乘以記錄長度,立即尋找主文件中的正確位置(假設這些值適合您的數據類型)。

因此,像僞代碼:

def getline(fhandle,reclen,recnum): 
    seek to position reclen*recnum for file fhandle. 
    read reclen characters into buffer. 
    return buffer. 
+0

camh有一個更好的解決方案,但是我將在這裏留下這個記錄不是固定長度的情況。 – paxdiablo 2010-05-08 12:55:25

+0

謝謝你,非常豐富。 – JavaRocky 2010-05-08 13:01:17

14

head -10 file | tail -1回報10號線可能緩慢,但。

here

# print line number 52 
sed -n '52p' # method 1 
sed '52!d' # method 2 
sed '52q;d' # method 3, efficient on large files 
+0

當您在尋找32696行時更爲有用。 – Amanda 2012-11-28 15:07:07

2

一個awk替代方案,其中3是行號。

awk 'NR == 3 {print; exit}' file.txt 
+0

更好的打印和退出,所以awk不會通過文件的其餘部分。 – ghostdog74 2010-05-08 14:29:53

+0

非常好的一點 – Jamie 2010-05-08 14:59:24

1

快速perl的一個班輪將工作做好這個太...

$ perl -ne 'if (YOURLINENUMBER..YOURLINENUMBER) {print $_; last;}' /path/to/your/file 
2

使用qsed使搜索停止線已被打印後。

sed -n '11723{p;q}' filename 

的Python(最小錯誤檢查):

#!/usr/bin/env python 
import sys 

# by Dennis Williamson - 2010-05-08 
# for http://stackoverflow.com/questions/2794049/getting-one-line-in-a-huge-file-with-bash 

# 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) 

參數驗證應該是好多了,有房有許多其他方面的改進。

相關問題