2014-07-10 36 views
3

有哪些選項可用於在超大文件上進行字數統計?在非常大的文件(運行時耗盡內存)中計數word出現grep -o foo | wc -l

我相信整個文件在1行,這可能是問題的一部分,正如下面的答案之一所指出的。

在這種情況下,我有一個1.7 Gb的xml文件,並試圖快速計算其中的一些內容。

我發現這個職位 Count number of occurrences of a pattern in a file (even on same line) 和方法爲我工作達到一定的規模。

高達300MB左右(40 000)的出現很好做

cat file.xml | grep -o xmltag | wc -l  

但規模以上,我得到 「內存耗盡」。

+3

你試過這個'grep -o'xmltag'file.xml | wc -l' –

+0

Ref Raj請注意,您不應該在可以讀取數據本身的程序中使用'cat'。它減慢了程序並使其更加複雜。 – Jotne

+0

是的,不知何故,你需要將文件拆分成塊。請注意,這種拆分可能是任意的,但是,由於每個塊有一個拆分詞,因此您的字數可能會增加(塊的數量 - 1)。 –

回答

0

嘗試使用GNU Parallel這樣的...它會分裂成file.xml(在最近的新行或左右)1MB的塊,每塊傳遞到一個CPU核心運行grep,所以不僅要它的工作,但它應該工作速度更快太:

parallel --pipe grep -o xmltag < file.xml | wc -l 
0

http://lists.gnu.org/archive/html/parallel/2014-07/msg00009.html

例:Grepping對於m的正則表達式n行。

到grep一個大文件進行了大量正則表達式的最簡單的解決方法是:

grep -f regexps.txt bigfile 

或者,如果正則表達式是固定字符串:

grep -F -f regexps.txt bigfile 

有2個限制因素:CPU和磁盤I/O。 CPU很容易測量:如果grep的CPU佔用率> 90%(例如,當運行在頂端)時,那麼CPU就是一個限制因素,並行化將加快速度。如果不是 ,那麼磁盤I/O是限制因素,並且根據磁盤 系統,並行化可能會更快或更慢。知道 的唯一方法就是測量。

如果CPU是限制因素並行應在正則表達式來完成:

cat regexp.txt | parallel --pipe -L1000 --round-robin grep -f - bigfile 

這將啓動一個grep的每個CPU和讀取大文件每CPU, 一個時間,但作爲並行完成,除第一個之外的所有讀取將被緩存在RAM中的 。根據regexp.txt的大小,可能會更快地使用 --block 10m而不是-L1000。如果regexp.txt太大而不適合 RAM,請刪除--round-robin並調整-L1000。這將導致bigfile 被讀取更多次。

某些存儲系統在並行讀取 多個塊時性能更好。這對於某些RAID系統和某些網絡文件系統來說是正確的。並行大文件的閱讀:

parallel --pipepart --block 100M -a bigfile grep -f regexp.txt 

這將大文件分割成塊100MB並在每個 這些塊運行的grep。並行大文件和regexp.txt 的同時在讀取使用--fifo將二者結合起來:

parallel --pipepart --block 100M -a bigfile --fifo cat regexp.txt \| parallel --pipe -L1000 --round-robin grep -f - {} 
1

多少換行符在你file.xml?如果你的一行很長,這可能解釋爲什麼grep會以「grep:memory exhausted」失敗。

解決方案是在\ n引入\ n並不重要的地方。說,每一個</前:

cat big.xml | perl -e 'while(sysread(STDIN,$buf, 32768)){ $buf=~s:</:\n</:; syswrite(STDOUT,$buf); }' 

GNU並行可以砍下大文件成小塊。再次,你將需要找到不在比賽中間的好切碎場所。對於XML的好地方往往會之間>和<:

parallel -a big.xml --pipepart --recend '>' --recstart '<' --block 10M grep -o xmltag 

更妙的是代表一個記錄的結束結束標記:

parallel -a big.xml --pipepart --recend '</endrecord>' --block 10M grep -o xmltag 

注意--pipepart是一個相對較新的選擇,所以你需要版本20140622或更高版本。

+0

我相信整個文件是1行 – user985366