我有一個文件太大而不適合內存。 shuf
似乎在RAM中運行,並且sort -R
不混洗(相同的行最後彼此相鄰;我需要將所有行混在一起)。除了滾動我自己的解決方案之外,還有其他選擇嗎bash - 將一個文件太大而無法放入內存中
回答
使用decorate-sort-undecorate模式的一種形式,awk
你可以這樣做:
$ seq 10 | awk 'BEGIN{srand();} {printf "%06d %s\n", rand()*1000000, $0;}' | sort -n | cut -c8-
8
5
1
9
6
3
7
2
10
4
對於一個文件,你會怎麼做:
$ awk 'BEGIN{srand();} {printf "%06d %s\n", rand()*1000000, $0;}' SORTED.TXT | sort -n | cut -c8- > SHUFFLED.TXT
或cat
管道開始處的文件。
這個工作方式是生成一列000000
和999999
之間的隨機數字(裝飾);在該列上排序(排序);然後刪除列(undecorate)。這應該在排序不理解數字的平臺上工作,方法是生成一個具有前導零的列以進行詞典排序。
您可以增加隨機化,如果需要的話,在幾個方面:
如果你的平臺的
sort
瞭解數值(POSIX,GNU和BSD這樣做),你可以做awk 'BEGIN{srand();} {printf "%0.15f\t%s\n", rand(), $0;}' FILE.TXT | sort -n | cut -f 2-
使用接近雙浮子隨機表示。如果您僅限於詞典排序,只需將兩個調用合併到一個列中,如下所示:
awk 'BEGIN{srand();} {printf "%06d%06d\t%s\n", rand()*1000000,rand()*1000000, $0;}' FILE.TXT | sort -n | cut -f 2-
它提供了一個12位數的隨機組合。
計數行(wc -l
)並按隨機順序生成與行號相對應的數字列表 - 可能是通過生成臨時文件中的數字列表(使用/tmp/
,通常位於RAM中,因此速度相對較快)。然後按照混洗號碼的順序將每個號碼對應的行復制到目標文件中。
由於在文件中尋找換行符的數量,這樣做效率會很低,但它幾乎適用於任何大小的文件。
如何: perl <large-input-file -lne 'print rand(), "\t", $_' | sort | perl -lpe 's/^.*?\t//' >shuffled-output-file
如果文件中有什麼可以裝入內存大小的幾個數量級之內,一個選擇是隨機分配中(比如說)1000個臨時文件中的行,然後洗牌每個這些文件並連接結果:
perl -we ' my $NUM_FILES = 1000;
my @fhs;
for (my $i = 0; $i < $NUM_FILES; ++$i) {
open $fh[$i], "> tmp.$i.txt"
or die "Error opening tmp.$i.txt: $!";
}
while (<>) {
$fh[int rand $NUM_FILES]->print($_);
}
foreach my $fh (@fhs) {
close $fh;
}
' < input.txt \
&& \
for tmp_file in tmp.*.txt ; do
shuf ./"$tmp_file" && rm ./"$tmp_file"
done > output.txt
(當然,也將在臨時文件—的尺寸有一些變化,他們不會全部是正好千分之一原始文件—的大小,因此,如果您使用這種方法,你需要在更多方面犯錯,更小的文件)。
赦免最初的誤讀 - 我希望downvoter不相信我錯誤的分析。這是一個完全合理的方法。 –
@CharlesDuffy:不用擔心。我*猜測* downvoter實際上是l'L'l。 (即使不是,我現在認爲dawg的答案比我的答案更好,所以我不太關心這個答案。:-P) – ruakh
看看https://github.com/alexandres/terashuf。從頁面:
terashuf實現了利用有限的內存
- 1. 我的JSON文件太大而無法放入內存,我該怎麼辦?
- 2. rmd文件太大而無法打開
- 3. 將.html中的變量傳遞給.php文件太大而無法放入URL中?
- 4. 如何在XML數據太大而無法放入內存時訪問Java中XML數據的子集?
- 5. 無法打開,無法寫入:文件太大
- 6. 無法通過phpmyadmin文件大小導入數據庫太大
- 7. 時間戳太大,無法保存在一個int變量中
- 8. 合併大文件而不將整個文件加載到內存中?
- 9. 將大文件放入列表中
- 10. Keras處理無法放入內存的大型數據集
- 11. 當文件無法放入火花的主內存中時,火花如何讀取大文件(petabye)
- 12. 計算文件中的行數而不將整個文件讀入內存?
- 13. 內存問題downloding一個大文件
- 14. 在python中加載一個.csv文件,消耗太多內存
- 15. 將方法的結果放入另一個.m文件中
- 16. 將文件讀入內存?
- 17. 緩存內存中的一個大文件的java中
- 18. 我想將一個XML文件內容放入一個URL中,我可以嗎?
- 19. 不能用安全的FTP將文件放入內存中
- 20. couchbase無法存儲,因爲太大
- 21. 如何查看太大而無法在編輯器中打開的.sql文件?
- 22. CLOB值太大,無法插入DB2表
- 23. 無法釋放內存C
- 24. 計劃是太大,無法在內存Pyinstaller
- 25. 使用UTI將文件的內容放入NSPasteboard而非NSFileContentsPboardType?
- 26. 把csv文件放入內存
- 27. Bash:遞歸地將一行寫入列最大的文件
- 28. 無法將輸出放入一個變量
- 29. 將大文件寫入Blob存儲和內存不足
- 30. 無法將文件夾從一個項目拖放到xcode4中的另一個
尼斯洗牌 多TB的文本文件準洗牌算法。因爲'sort'分成多個文件來處理大於內存的內容(GNU版本,無論如何),這實際上應該工作。 –
+1 - 好主意。請注意,因爲'sort'執行穩定的排序,所以這不會是100%完美的洗牌:如果A行在輸入的B行之前,這種方法稍微有可能在行B之前將A行放在輸出中。爲了解決這個問題,你可以通過編寫諸如'seq 10 |的東西來反轉編號和混洗grep -n''| sort -R |切掉-d:-f2-'代替。 (但即使沒有這種變化,我認爲它可能是好的:我認爲它應該非常接近隨機排序。) – ruakh
@ruakh:謝謝。你是對的 - 由於「排序」具有穩定的排序,所以它略有維持秩序的傾向。它具有0到1000000之間的隨機數字,因此這隻會是連續兩行中相同隨機數的問題。另一種更加隨機的方法是添加更多數字或第二列隨機數字。 – dawg