CSVデータを複数の個別ファイルにフィルタリング

CSVデータを複数の個別ファイルにフィルタリング

次の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"

関連情報