2 番目の列に基づいてデータをグループ化

2 番目の列に基づいてデータをグループ化

次の行を含むファイルがあります。

1 a
2 a
3 a
1 b
2 b
1 c
2 c
3 c
4 c
1 d

私が得たい結果は次のとおりです。

a 1 2 3
b 1 2
c 1 2 3 4
d 1

答え1

使用awk:

awk '{ group[$2] = (group[$2] == "" ? $1 : group[$2] OFS $1 ) }
     END { for (group_name in group) print group_name, group[group_name] }' inputfile

これにより、グループは名前付き配列に保存されますgroup。配列はグループ名(入力データの2番目の列)でインデックス付けされ、入力の各行に対してinputfile最初の列の値が正しいグループに追加されます。

このENDブロックは、収集されたすべてのグループを繰り返して、グループ名とそのグループの項目を出力します。

このawkプログラムはより良いレイアウトを持っています:

{
    group[$2] = (group[$2] == "" ? $1 : group[$2] OFS $1 )
}

END {
    for (group_name in group)
        print group_name, group[group_name]
}

これはいいえgroupアレイが実際に大量のデータを保存している場合はどうすればよいですか?みんなファイルから読み取った入力データです。

大規模データの場合、入力は次のようになります。ソート済みグループ名(2番目の列)には、次を使用します。

awk '$2 != group_name { if (group != "") print group_name, group; group = ""; group_name = $2 }
    { group = (group == "" ? $1 : group OFS $1) }
    END { if (group != "") print group_name, group }' inputfile

これは、現在のグループが何であるかを追跡し、そのグループに関するデータを収集します。入力の2番目の列が別の値に切り替えられるたびに、収集されたグループデータを出力して新しいデータ収集を開始します。これは、入力データセット全体ではなく数行の入力のみが保存されることを意味します。

最後のawkプログラムのレイアウトが良いです。

$2 != group_name {
    if (group != "")
        print group_name, group

    group = ""
    group_name = $2
}

{
    group = (group == "" ? $1 : group OFS $1)
}

END {
    # Output last group (only), if there was any data at all.
    if (group != "")
        print group_name, group
}

答え2

この試み、

for i in  `awk '!a[$2]++ { print $2}' file.txt`
do
        echo "$i `awk -v z=$i '$2==z{print $1}' file.txt | tr '\n' ' '`"
done
  • awk '!a[$2]++ { print $2}列 2 の固有値を提供します。
  • $2==z{print $1}変数$ 2のすべての値を等しく印刷しますz

答え3

注文する:for i in a b c d; do echo $i;awk -v i="$i" '$2 == i{print $1}' filename| perl -pne "s/\n/ /g";echo " "| perl -pne "s/ /\n/g";done| sed '/^$/d'| sed "N;s/\n/ /g"

出力

for i in a b c d; do echo $i;awk -v i="$i" '$2 == i{print $1}' l.txt | perl -pne "s/\n/ /g";echo " "| perl -pne "s/ /\n/g";done| sed '/^$/d'| sed "N;s/\n/ /g"

a 1 2 3 
b 1 2 
c 1 2 3 4 
d 1

関連情報