次のファイルを検討してください。
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
OFS=FS
一貫性に設定します。awk
使用多次元配列$2
今まで向き合った価値を思い出してください。一致するものがない場合にのみ「続き」()してください!(($1,$2)in c)
。- 新しいキーが最初に見つかった場合は、多次元配列に「ダミー」値を提供します。
- 便宜上、目的の出力文字列を別の配列に連結します。
- で
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