Awk
AWK 根據 1 列的內容將輸入 CSV 拆分為多個輸出文件
一個文件
data.csv
有以下數據1,avocado,mexican green fruit 1,kiwi,green fruit 1,banana,yellow fruit 1,mango,yellow fruit
要將數據組織成水果類別,我已經完成了
awk -F ',' '{print >> ($3 ".csv")}' data.csv
它創建了 3 個文件,
mexican green fruit.csv
,green fruit.csv
,yellow fruit.csv
我希望將這些文件名稱中的空格替換為下劃線
_
所以,文件名應該是
mexican_green_fruit.csv
,green_fruit.csv
,yellow_fruit.csv
在這一班輪中需要幫助
awk
才能做到這一點尋找
awk
唯一的答案
GNU awk 的僅 awk 答案(如 OP 所要求的)將是:
awk -F',' '{print > gensub(/[[:space:]]+/,"_","g",$3) ".csv"}' data.csv
如果您的輸入足夠小以至於您不能超過“打開的文件過多”門檻值,則任何 POSIX awk 的僅 awk 答案將是:
awk -F',' '{out=$3 ".csv"; gsub(/[[:space:]]+/,"_",out); print > out}' data.csv
如果您可能超過“打開的文件過多”門檻值,則任何 POSIX awk 的僅 awk 答案將是:
awk -F',' '{out=$3 ".csv"; gsub(/[[:space:]]+/,"_",out); if (!seen[$3]++) printf "" > out; print >> out; close(out)}' data.csv
但是最後一個會很慢,因為它會關閉並重新打開每次寫入的輸出文件,並且它假設您可以將每個
$3
值儲存在記憶體中。您可以通過僅在輸出文件更改時關閉輸出文件來提高效率:awk -F',' '$3 != prev {close(out); out=$3 ".csv"; gsub(/[[:space:]]+/,"_",out); if (!seen[$3]++) printf "" > out; prev=$3} {print >> out}' data.csv
如果您對不是僅 awk 的答案感到滿意,那麼使用任何 POSIX awk、排序和剪切的 DSU(裝飾/排序/取消裝飾)習語,以下內容對於任何大小的輸入文件都將有效且穩健地工作可以
sort
處理(並且它被設計為使用按需分頁等來處理非常大的文件),並且對於任意數量的輸出文件:$ cat tst.sh #!/usr/bin/env bash awk ' BEGIN{ FS=OFS="," } { print $3,NR,$0 } ' "${@:-}" | sort -t',' -k1,1 -k2,2n | cut -d',' -f3- | awk ' BEGIN{ FS=OFS="," } $3 != prev { close(out) out = $3 ".csv" gsub(/[[:space:]]+/,"_",out) prev = $3 } { print > out } '
$ ./tst.sh data.csv
$ head *.csv ==> data.csv <== 1,avocado,mexican green fruit 1,kiwi,green fruit 1,banana,yellow fruit 1,mango,yellow fruit ==> green_fruit.csv <== 1,kiwi,green fruit ==> mexican_green_fruit.csv <== 1,avocado,mexican green fruit ==> yellow_fruit.csv <== 1,banana,yellow fruit 1,mango,yellow fruit
有關 DSU 的更多資訊,請參閱https://stackoverflow.com/questions/71691113/how-to-sort-data-based-on-the-value-of-a-column-for-part-multiple-lines-of- af/71694367#71694367。