フィールドに関連するすべてのデータを印刷する

フィールドに関連するすべてのデータを印刷する

次のファイルを検討してください。

foo,5
foo,7
foo,9
boo,5
boo,10
boo,10

私が望むのは、$2レコードに関連するすべてのデータを印刷することです。$1

この例では、目的の出力は次のようになります。

foo,5,7,9
boo,5,10

答え1

解決策awk

awk 'BEGIN{OFS=FS=","}!(($1,$2)in c){c[$1,$2]=1;r[$1]=r[$1] OFS $2}
            END{for(i in r){print i r[i]}}' file
  1. OFS=FS一貫性に設定します。
  2. awk使用多次元配列$2今まで向き合った価値を思い出してください。一致するものがない場合にのみ「続き」()してください!(($1,$2)in c)
  3. 新しいキーが最初に見つかった場合は、多次元配列に「ダミー」値を提供します。
  4. 便宜上、目的の出力文字列を別の配列に連結します。
  5. ENDループを印刷します。
    • ループ反復は特定の順序ではなく、awk必要に応じてソート機能を使用できます。

答え2

データを「ハッシュ」、「連想配列」、「辞書」、または何と呼ぶか​​を解析します。

perl -F, -lane '$first{$F[0]}->{$F[1]} = (); END { print join(",", $_, sort { $a <=> $b } keys %{ $first{$_} } ) for keys %first }' < inputfile

答え3

Bashでawkのないソリューション:

$ cat bla.txt 
foo,5
foo,7
foo,9
boo,5
boo,10
boo,10

$ { buffer="";
  while read i ; do
    key="${i%,*}" ;
    if [[ "$key" == "$oldkey" ]] ; then
      idx="${i#*,}";
      if [[ ! "$idx" == "$oidx" ]] ; then
        buffer+=",$idx" ;
        oidx="$idx";
      fi ;
    else
      test -z $buffer || echo $buffer ;
      oldkey="$key" ;
      buffer="$i" ;
      oidx="${i#*,}" ;
    fi ;
  done ; echo $buffer ; } < bla.txt
foo,5,7,9
boo,5,10
$

きれいでも短くもありませんが、うまくいきます。私もawkソリューションを見ることに興味があります。

答え4

そしてgnu datamash:

datamash -t ',' -s -g 1 unique 2 <infile

出力値の順序は処理前にソートされるため異なります。

boo,10,5
foo,5,7,9

関連情報