複数列の並べ替え

複数列の並べ替え

内容は次のようなファイルがあります。

19.58 1925 Alpha
20.40 1924 Otter
13.66 1920 Gold

以下を出力するために「列基準」でソートしようとしています。

13.40 1920 Alpha
19.58 1924 Gold
20.66 1925 Otter

次のようなさまざまなコードの組み合わせを試しました。

cat files | sort -t. -k1,1n | sort -t " " -k2,2n -k3,3r k4,4n

しかし、これは所望の結果を出力しない。私が言及したソートをどのように達成できますか?

答え1

printf "%s.%s %s %s\n" $(paste <(awk -F'[. ]' '{print $1}' file | sort -n) <(awk -F'[. ]' '{print $2}' file | sort -n) <(awk -F'[. ]' '{print $3}' file | sort -n) <(awk -F'[. ]' '{print $4}' file | sort))

出力:

1920 13.40アルファ
19.58 1924年金
20.66 1925カワウソ

答え2

GNUがある場合は、awk特別な配列の助けを借りてソートを実行できますPROCINFO

awk -F '[. ]' '{for(i=1;i<NF+1;i++) a[i][NR]=$i} \
    END{PROCINFO["sorted_in"]="@val_num_asc"; \
        for(j=1;j<NF+1;j++){ I=0; for(i in a[j]) A[++I][j]=a[j][i]} \
            for(i=1;i<NR+1;i++){ printf A[i][1]"."; \
                for(j=2;j<NF+1;j++) printf A[i][j]" "; printf "\n"}}' file

上記のコードは一見すると複雑に見えますが、実際には非常に簡単です。ファイル全体を配列に保存し、a最後にA必要に応じて配列を使用します。主なトリックは、@val_num_asc数値の昇順で列をソートしようとするときに使用されます。

行数と列数に関係なく機能する必要があります。ファイル全体がメモリに保存されるため、大きなテーブルの場合は遅くなる可能性があることを覚えておいてください。

答え3

#!/bin/sh

for i in 1 2 3 4
do
    tr . " " < "${1:?}" | cut -d' ' -f$i | sort > $$-$i
done

paste -d. $$-[12] | paste -d' ' - $$-[34]

rm $$-[1234]

関連情報