zgrep 在多個文件中的性能緩慢
我有一個9.8GB的 gzip 文件 A.gz,而我擁有的其他文件是79MB B.txt,每行都有一些文本。我想在 A.gz 中 grep B 的文本並寫入一個新文件。
最初,我使用了這個命令
zgrep -f B.txt A.gz > C.xml
但是這個命令被掛了,它創建了一個空的 C.xml 很長一段時間。
然後在Google搜尋之後我才知道,因為 B.txt 很大,當它將文本保存在緩衝區中時它會掛起。
所以我將文本文件拆分為 20000 個文本
split -l 20000 -a 4 B.txt B
我創建了諸如 Baaaa、Baaab 之類的文件….
然後遍歷每個文件
cd B for f in B*; do zgrep -f "$f" ../A.gz >> C.xml done
它非常慢並且仍在執行。
有什麼更好的方法嗎?
gunzip 壓縮 gz 文件會提高性能嗎?
更新
我試過 -F
zgrep -F -f "$f" ../A.gz >> C.xml
這有點快,但仍然需要其他選擇
我有xml之類的
<root> <source>source1</source> <Id>123</Id> <category>ABC</category> </root> <root> <source>source2</source> <Id>123</Id> <category>XYZ</category> </root>
這裡 id 相同 123 但類別不同 ABC 和 XYZ
(輸入是有限的類別集,例如 ABC、DEF、GHI、JKLM、NOP)最初我的類別為 ABC,因此基於類別 ABC 我找到了它的 id 即 123 像這樣我繼續寫屬於這些的所有 id將類別輸入到新文件,即 B.txt(id 列表),如下所示
zgrep -E 'ABC|DEF|GHI|JKLM|NOP' A.gz | sed -n 's:.*<Id>\(.*\)</Id>.*:\1:p' | uniq > B.txt
稍後我遍歷這個id並獲取所有xml,這樣我得到了屬於id 123的類別ABC和XYZ的xml標籤
一個 79MByte 的 grep “字元串” 使用起來會很痛苦。是
B.txt
真正的正則表達式的行還是它們固定相同的字元串?如果它們是固定字元串,它們在A.gz
整行中是否相同?未壓縮中的多少行A.gz
預計與 中的行匹配B.txt
?模式匹配建議
如果行中的行
B.txt
確實是正則表達式或行的子字元串,則A.gz
可能會被迫使用HyperScan之類的東西,它旨在處理大量正則表達式。如果您有磁碟空間,您可以解壓縮A.gz
並讓 HyperScan 開始工作(您甚至可以讓 shell 在 HyperScan 搜尋時動態解壓縮)。另一種嘗試是ripgrep。全線匹配建議
如果您正在處理固定的完整行字元串,
B.txt
並且未壓縮的字元串A.gz
包含相對較小的匹配行(比如說大約 100MB),那麼您最好編寫一個程序來進行預處理A.gz
:
- 您可以散列每一行
B.txt
並記住散列- 然後,您檢查未壓縮
A.gz
散列中的任何行是否與您之前的任何散列相同。如果是這樣,您列印出該行(例如 intoC.txt
)以供進一步處理- 你現在做最後一次通過,你更嚴格地檢查每一行是否
B.txt
在C.txt
裡面(反之亦然 - 取決於哪個文件更小)一些用於進行初始近似過濾的程式碼可能是這樣的:
# Do a quick APPROXIMATE filter of lines in FILENEEDLES that are also in # FILEHAYSTACK import sys def main(): if len(sys.argv) < 2: print("usage: %s FILENEEDLES FILEHAYSTACK" % sys.argv[0]) exit(1) first_filename = sys.argv[1] second_filename = sys.argv[2] line_hashes = set() with open(first_filename, "r") as f: for line in f: line_hashes.add(hash(line)) with open(second_filename, "r") as f: for line in f: if hash(line) in line_hashes: sys.stdout.write(line) if __name__ == "__main__": main()
例如:
$ echo -e '1\n2\n3' > B.txt $ echo -e '2\n3\n4\5' | gzip > A.gz $ ./approxfilter.py B.txt <(gzip -dc A.gz) > candidates.txt $ cat candidates.txt 2 3
您現在需要檢查 Candidate.txt 以查看行輸出是否完全匹配
B.txt
(但希望這是一個更小且更容易的問題,如果候選行的數量“小”,您甚至可以修改上面的程序來完成所有操作"並且完全在記憶體中可以保存的範圍內)。(發問者後來在評論中澄清說他們沒有使用全行長度的字元串,所以這種方法不起作用)