(AWK) Csv列の同じ変数を別のファイルに分割する

(AWK) Csv列の同じ変数を別のファイルに分割する

2つの列を持つtest1.csvファイルがあります。

group,email
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]

私の目標は、最初の列の値に基づいて別々のテキストファイルを作成することです。

たとえば、

最初のファイル名は[Eメール保護]そして包含

[email protected]
[email protected]
[email protected]
[email protected]

最初のファイル名は[Eメール保護]そして包含

[email protected]
[email protected]

など。

このawkコマンドがあります

awk -F"," 'NR==1{header=$0}NR>2&&!a[$1]++{print header > (""$1"")}NR>2{print > (""$1"")}' test1.csv

しかし、ファイル名が正しく指定されているにもかかわらず、結果は私が本当に望むものではありません。

group,email
[email protected],[email protected]
[email protected],[email protected]
[email protected],[email protected]

さらに、.csvファイルが大きすぎるたびに、「Awk:開いたファイルが多すぎます」というメッセージが表示されます。

助けてくれてありがとう。また、sedやgrepなどの他の言語も見てください。

答え1

これがあなたに必要なものです:

awk -F ',' 'NR<2{next} p1!=$1&&p1{close(p1)} {p1=$1;print $2>p1}' file
  • NR<2{next}:タイトルをスキップします。
  • p1!=$1&&p1{close(p1)}p1前の行の最初のフィールド()が現在の行の最初のフィールドと異なる場合は、「あまりにも開いているファイル」が発生しないように、古い出力ファイルが閉じられます(まだ開かれていない限り)。そして開くp1)。未設定)。
  • {p1=$1;print $2>p1}:最初のフィールドをp1変数に入れ、2番目のフィールドを最初のフィールド名のファイルに出力します。

file上記のawkでは、提供された例に示されているように、最初のフィールドは同じ行が一緒にグループ化されていると想定しています。そうでない場合、簡単な解決策はawkにソートされた入力を提供し、ヘッダーを明示的にスキップすることです(ヘッダーが最初の行にないため)。

sort file | awk -F ',' '/^group,email$/{next} p1!=$1&&p1{close(p1)} {p1=$1;print $2>p1}'

答え2

awk指定されたファイル名に直接リダイレクトできます(ドメイン名はスペースに安全でなければなりません)。$2$1

awk -F, 'NR>1{print $2 > $1}' file

ヘッダーをスキップしてファイルを開いたままにします。ヘッダー++h[$1]==1を書き込む新しいファイルかどうかをテストし、次を使用して追加することでこの問題を解決できます。>>>$2close($1)

awk -F, '
  NR==1{header=$0}
  NR>1{
    if(++h[$1]==1)print header > $1; 
    print $2 >> $1; close ($1)
}' file

重複を避けるために、++f[$0]==1添付する前にテストしてください。

awk -F, '
  NR==1{header=$0}
  NR>1&&++f[$0]==1{
    if(++h[$1]==1)print header > $1; 
    print $2 >> $1; close ($1)
}' file
head *.com

==> [email protected] <==
group,email
[email protected]
[email protected]
[email protected]
[email protected]

==> [email protected] <==
group,email
[email protected]
[email protected]

==> [email protected] <==
group,email
[email protected]
[email protected]
[email protected]

ファイルが完全にまたは部分的にソートされている場合は、次のように各行を盲目的に開閉することを防ぎます。

awk -F, '
  NR==1{header=$0}
  NR>1&&++f[$0]==1{
    if ($1 != old) close(old);
    if(++h[$1]==1)print header > $1; 
    print $2 >> $1; old=$1
}' file

これはデータファイルを使用しているため、$2 >> 2番目のブロックがあっても問題はなく、$1 新しいブロックによって削除されません。>

答え3

ミラーの使用(https://github.com/johnkerl/miller)簡単に言うと

mlr --csv put -q 'tee > $group, $*' ./input.csv
mlr -I --c2n cut -f email ./group*@*

これは奇妙なことではありませんが、あなたに効果があると思いました。

答え4

$ awk '{print (NR>1),$0}' file | sort -k1,1n -k2 | cut -d' ' -f2- |
    awk -F, '
        NR==1 { hdr=$0; next }
        $1 != out { close(out); out=$1; print hdr > out }
        { print $2 " > " out }
    '

上記のコードは、ほぼすべてのサイズの入力ファイルのすべてのawkで動作し、入力行の順序は関係なく高速です。

テスト完了後、実際に出力ファイルを生成するprint $2 " > " outように変更されました。print $2 > out

関連情報