2017-01-03 44 views
1

我期待從大型(約870,000,000行)文本文件中拉出某些行組。例如,在50行文件中,我可能需要第3-6,18-27和39-45行。從大型文本文件中讀取行組

從瀏覽堆棧溢出,我發現bash命令:

tail -n+NUMstart file |head -nNUMend 

是讓單行或起於NUMstart和去NUMend線組的最快方法。然而,當閱讀多組線時,這看起來效率低下。通常情況下這種技術不會太重要,但是對於這樣大的文件,它會產生巨大的差異。

有沒有更好的方法去比這對每一組行使用上述命令呢?我假設答案很可能是一個bash命令,但是真正開放給任何能夠最好地完成工作的語言/工具。

回答

3

要顯示線3-6,18-27和39-45使用sed:

sed -n "3,6p;18,27p;39,45p" file 

也可以養活從sed的一份文件。

內容文件foobar的:

 
3,6p 
18,27p 
39,45p 

用法:

sed -n -f foobar file 
+0

我很好奇,如果這會比'awk'快得多。 – codeforester

+1

這將掃描整個文件,最後一行之後退出的速度不能快於'awk'。 – karakfa

+2

將'45q'添加爲最後一個命令可以解決這個問題。 –

0

tail -n XX file | head -n YY對於不同範圍的問題是您正在多次運行它,因此效率低下。否則,benchmarks建議他們是最好的解決方案。

對於這個特定的情況下,您可能需要使用awk

awk '(NR>=start1 && NR<=end1) || (NR>=start2 && NR<=end2) || ...' file 

你的情況:

awk '(NR>=3 && NR<=6) || (NR>=18 && NR<=27) || (NR>=39 && NR<=45)' file 

也就是說,你組的範圍,讓awk打印相應的線路時,他們發生,只是循環一次文件。添加最後一個NR==endX {exit}endX是最後一個範圍內的結束項目),以便在它讀取最後一條有趣的行後完成處理可能也很有用。

你的情況:

awk '(NR>=3 && NR<=6) || (NR>=18 && NR<=27) || (NR>=39 && NR<=45); NR==45 {exit}' file 
1

awk來救援!

awk -v lines='3-6,18-27,39-45' ' 
     BEGIN {n=split(lines,a,","); 
       for(i=1;i<=n;i++) 
       {split(a[i],t,"-"); 
       rs[++c]=t[1]; re[c]=t[2]}} 

      {for(i=s;i<=c;i++) 
       if(NR>=rs[i] && NR<=re[i]) {print; next} 
       else if(NR>re[i]) s++; 
       if(s>c) exit}' file 

提供最後打印行後的提前退出。沒有錯誤檢查,範圍應該按遞增順序提供。

+0

好的方法。但是,我不認爲範圍饋送在這裏是一個特別的問題,所以'BEGIN'塊對我來說無關緊要。 – fedorqui