
ファイル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
mexican green fruit.csv
、、、green fruit.csv
3つのファイルを作成します。yellow fruit.csv
このファイル名のスペースを下線に変更したいと思います。_
したがって、ファイル名はmexican_green_fruit.csv
、、でなければなりません。green_fruit.csv
yellow_fruit.csv
awk
そのためにはこの裏地の助けが必要です。
awk
唯一の答えを探しています。
答え1
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を使用するのではなく、ソートとトリミングのための装飾/並べ替え/装飾解除(DSU)イディオムであるPOSIX awkを使用するという答えに満足している場合は、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。
答え2
これは、次の関数を使用して実行できます。
awk -F, '
function csvfile(name) {
gsub(/[[:space:]]+/, "_", name)
return name".csv"
}
{print >> csvfile($3)}'
ここでは、各シーケンスの1つ以上のスペース文字(スペース、タブ、cr ...を含む)がで置き換えられます_
。
答え3
(gnu awkなどを使用して)次のように実行できます
awk -F, '{print > gensub(/ /,"_","g",$3)".csv"}' ex.csv
gensub
機能的なものですsub
- 書くのは少し簡単です。>
>>
このコマンドを実行する前にcsvを生成しない限り、それよりも優れています。- 何百万もの異なる3ドルの価値がある場合、問題が発生する可能性があります。
編集する:新しい要件に対応(実際には新しい問題)
awk -F, '
NF == 0 {next}
!seen[$3]++ {print "Quantity, f..., c..." > gensub(/ /,"_","g",$3)".csv"}
{print > gensub(/ /,"_","g",$3)".csv"}
' ex.csv