次のCSVファイルがありますfile1.csv
。
something;AD;sss;Andorra;nothing;type_1;sss
something222;AD;sss222;Andorra;nothing222;type_2;aaa
thing;NL;thing3;Netherlands;thing;type_2;bb
etc;US;etc;United States;etc;type_2;nothing
国ごとに別々のファイルを作成したいです。私は次のようにgrepを作成します。
grep -e "\;AD\;.*\;Andorra\;" file1.csv > fileAD.csv
grep -e "\;NL\;.*\;Netherlands\;" file1.csv > fileNL.csv
grep -e "\;US\;.*\;United\sStates\;" file1.csv > fileUS.csv
これは効果がありますが、世界中のすべての国があるため、各国に対してこの行を書きたくありません。他の解決策がありますか?
type_1
また、およびを含む列がありますtype_2
。この点を考慮する必要があります。国別ファイルをすべて作成したら、国別に新しいファイルを作成してtype_1
使用する必要がありますtype_2
。
たとえば、アンドラの場合は、次のファイルが必要です。
fileAD.csv
:something;AD;sss;Andorra;nothing;type_1;sss something222;AD;sss222;Andorra;nothing222;type_2;aaa
fileADtype_1.csv
:something;AD;sss;Andorra;nothing;type_1;sss
fileADtype_2.csv
:something222;AD;sss222;Andorra;nothing222;type_2;aaa
略語のある列だけを探すのは大丈夫だと思いますが、セキュリティ上の理由から2つの列が必要です。一つはフルネームAD
で、もう一つはフルネームです。Andorra
答え1
データが次のようになるとします。シンプルCSVデータ、つまりフィールドに区切り文字または改行が含まれていません。
awk -F ';' '
{
print > "file" $2 ".csv"
print > "file" $2 $6 ".csv"
}' file1.csv
これにより、各行が2回印刷されます。一度は2番目のフィールド値としてのみ指定されたファイルに、1回は2番目と6番目のフィールド値の組み合わせで指定されたファイルに印刷されます。質問のテキストによると、各出力ファイル名には文字列プレフィックスが付き、file
サフィックスが付いています。.csv
ファイル名に使用される2つのフィールドの値は検証されません。
4番目のフィールドに国名をマージするには:
awk -F ';' '
{
print > "file_" $2 "-" $4 ".csv"
print > "file_" $2 "-" $4 "_" $6 ".csv"
}' file1.csv
与えられたデータに対して次のファイルが生成されます。
file_AD-Andorra.csv
file_AD-Andorra_type_1.csv
file_AD-Andorra_type_2.csv
file_NL-Netherlands.csv
file_NL-Netherlands_type_2.csv
file_US-United States.csv
file_US-United States_type_2.csv
上記のコードはGNUを使用しているシステムでうまく機能しますawk
。他のawk
実装では、同時に書き込むためにあまりにも多くのファイルを開いたままにすると問題が発生する可能性があります。これらのawk
実装ではよりスマートでなければならず、ファイルに書き込んだ後はファイルを閉じることを覚えておく必要があります。ファイルが閉じられたら、>>
次にファイルにデータを書き込むときに印刷する必要があります。それ以外の場合、ファイルは切り捨てられます。
awk -F ';' '
function do_print(name) {
if (seen[name] == 1) print >>name # append to file
else print >name # first write, truncate file
close(name)
seen[name] = 1
}
{
do_print("file_" $2 "-" $4 ".csv")
do_print("file_" $2 "-" $4 "_" $6 ".csv")
}' file1.csv
awk
これにより、式を使用できないOpenBSDでもコードが実行されますprint >
。
追加(面白い):awk
コードからいくつかの統計を出力するようにします。
awk -F ';' '
function do_print(name) {
if (seen[name] > 0) print >>name # append to file
else print >name # first write, truncate file
close(name)
seen[name]++
}
{
do_print("file_" $2 "-" $4 ".csv")
do_print("file_" $2 "-" $4 "_" $6 ".csv")
}
END {
for (name in seen)
printf "Wrote %d lines to \"%s\"\n", seen[name], name >"/dev/stderr"
}' file1.csv
処理が終了すると、エラーストリームにいくつかの統計が記録されます。与えられたデータについて:
Wrote 1 lines to "file_NL-Netherlands.csv"
Wrote 1 lines to "file_US-United States_type_2.csv"
Wrote 1 lines to "file_AD-Andorra_type_1.csv"
Wrote 2 lines to "file_AD-Andorra.csv"
Wrote 1 lines to "file_NL-Netherlands_type_2.csv"
Wrote 1 lines to "file_US-United States.csv"
Wrote 1 lines to "file_AD-Andorra_type_2.csv"