Bash

拆分文件,將每個部分作為參數傳遞給腳本,並行執行每個腳本

  • August 1, 2014

我有一個包含 10000 個單詞的 words.txt(一行一行)。我有 5,000 份文件。我想查看哪些文件包含哪些單詞(單詞周圍有一個正則表達式模式)。我有一個 greps 文件和輸出命中的 script.sh。我想 (1) 將我的輸入文件拆分為較小的文件 (2) 將每個文件作為參數提供給 script.sh 並 (3) 並行執行所有這些。

我基於教程的嘗試遇到了錯誤

$parallel ./script.sh ::: split words.txt # ./script.sh: line 22: split: No such file or directory

我的 script.sh 看起來像這樣

#!/usr/bin/env bash

line 1 while read line
line 2  do
       some stuff
line 22 done < $1

我想我可以通過啟動 grep 命令的目錄中的文件將拆分輸出到目錄循環 - 但是如何優雅而簡潔地做到這一點(使用並行)?

您可以使用該split工具:

split -l 1000 words.txt words-

會將您的words.txt文件拆分為每個命名不超過 1000 行的文件

words-aa
words-ab
words-ac
...
words-ba
words-bb
...

如果省略前綴(words-在上面的範例中),則split用作x預設前綴。

要使用生成的文件,parallel您可以使用 glob:

split -l 1000 words.txt words-
parallel ./script.sh ::: words-[a-z][a-z]

您可能不需要臨時文件,因為您從 STDIN 讀取。所以真的沒有理由使用split. 通過使用擺脫文件--pipe

cat words | parallel --pipe -L 1000 -N1 ./script.sh

如果它真的只是你想要的 grep:

find dir-with-5000-files -type f | parallel -X grep -f words.txt 

如果words.txt太大而無法放入記憶體,您可以將其拆分:

find dir-with-5000-files -type f | parallel -X "cat words.txt | parallel --pipe grep -f -"

GNU Parallel 的手冊頁涵蓋瞭如何最有效地為 m 正則表達式 grep n 行:http ://www.gnu.org/software/parallel/man.html#example__grepping_n_lines_for_m_regular_expressions_

為大量正則表達式 grep 大文件的最簡單解決方案是:

grep -f regexps.txt bigfile

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

grep -F -f regexps.txt bigfile

有 2 個限制因素:CPU 和磁碟 I/O。CPU 很容易測量:如果 grep 佔用 >90% CPU(例如在執行 top 時),那麼 CPU 是一個限制因素,並行化將加快這一程序。如果不是,那麼磁碟 I/O 是限制因素,並且取決於磁碟系統,並行化可能更快或更慢。唯一確定的方法是測量。

如果 CPU 是限制因素,則應在正則表達式上進行並行化:

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

這將為每個 CPU 啟動一個 grep 並為每個 CPU 讀取一次大文件,但由於這是並行完成的,除第一個之外的所有讀取都將記憶體在 RAM 中。根據 regexp.txt 的大小,使用 –block 10m 而不是 -L1000 可能更快。如果 regexp.txt 太大而無法放入 RAM,請刪除 –round-robin 並調整 -L1000。這將導致大文件被讀取更多次。

一些儲存系統在並行讀取多個塊時性能更好。這適用於某些 RAID 系統和某些網路文件系統。並行讀取大文件:

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

這會將大文件拆分為 100MB 的塊並在每個塊上執行 grep。要並行讀取 bigfile 和 regexp.txt,請使用 –fifo 將兩者結合起來:

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

引用自:https://unix.stackexchange.com/questions/147111