coreutilsを使用してsort
16進値(フィールド)に基づいて数値をソートする方法は?こんなことを期待していた
sort -k3,3x file_to_sort
しかし、そのような状況はx
存在しません。
編集:これまで私が思いついた最高のソリューションは次のとおりです。
{ echo ibase=16; cut -d' ' -f3 file_to_sort; } |
bc | paste -d: - file_to_sort | sort -t: -k1,1n | cut -d: -f2-
cut -d' ' -f3
検索フィールドを分離し(もちろん異なる場合-k3,3
があります)、bc
10進数に変換します(大文字と0x
小文字を一致させるにはプレフィックスなしで大文字の16進数が必要です)。次に、列を連結し、ソートして分割します。
最小サンプル入力:
5 hhf 25
3 ezh ae
1 hdh d12
2 ukr 9f
4 jjk 7
期待される出力(hex
3番目の列でソートされたファイル):
4 jjk 7
5 hhf 25
2 ukr 9f
3 ezh ae
1 hdh d12
答え1
私は次のサンプルデータを使用します。
1 hdh d12
2 ukr 9f
3 ezh ae
4 jjk 7
5 hhf 25
アイデアは、10進形式のソートフィールドを使用してこのデータの新しいバージョンを生成することです。つまり、awk
1変換して各行の前に追加し、結果を並べ替え、最後のステップで追加されたフィールドを削除します。
awk '{val="0x" $3; sub("^0x0x","0x",val); print strtonum(val),$0 ;}' file |
sort -n |
sed 's/^[^ ]* //'
結果は次のとおりです。
4 jjk 7
5 hhf 25
2 ukr 9f
3 ezh ae
1 hdh d12
1これはGNUawk
機能を想定していますstrtonum()
。
答え2
解決策perl
:
$ perl -anle '
push @h, [$F[-1],$_];
END {
print for map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [$_->[1],hex($_->[0])] } @h;
}
' file
4 jjk 7
5 hhf 25
2 ukr 9f
3 ezh ae
1 hdh d12
説明する
ファイルを処理するときに配列の配列を作成します
@h
。各要素は配列参照であり[$F[-1],$_]
、最初の要素は比較する16進値であり、2番目の要素は行全体です。END
私たちが使うブロックではシュワルツ変換:各要素を使用して、
@h
行全体($_->[1]
各配列参照の2番目の要素@h
)と比較する16進値を含む匿名配列を作成します。hex($_->[0])]
16進値に基づいて上記の配列を並べ替えます。
$a->[1] <=> $b->[1]
ソートされた配列から各配列参照の最初の要素を取得し、
map { $_->[0] }
結果を印刷します。
修正する
@Joseph Rの提案に基づいて:
$ perl -anle '
push @h, [hex($F[-1]),$_];
END {
print $_->[1] for
sort { $a->[0] <=> $b->[0] } @h;
}
' file
アップデート2
Schwartzian変換を使用せずにStefanのコメントを読んだ後:
$ perl -e '
print sort {hex((split(/\s+/,$a))[-1]) <=> hex((split(/\s+/,$b))[-1])} <>;
' file
4 jjk 7
5 hhf 25
2 ukr 9f
3 ezh ae
1 hdh d12
答え3
入力する
$ cat /tmp/input
0x45 aaa 333
0x50 dd 33
0x4 bbbb 444
0x456 cc 22
0x5 eee 1111
ライナーの位置合わせ
$ gawk --non-decimal-data '{ dec = sprintf("%d", $1); print dec " " $0 }' /tmp/input | sort -n -k 1 | cut -f2- -d' '
0x4 bbbb 444
0x5 eee 1111
0x45 aaa 333
0x50 dd 33
0x456 cc 22
段階的に並べ替え
ステップ1:16進数の10進数表現を含む新しい最初の列を追加します。
$ gawk --non-decimal-data '{ dec = sprintf("%d", $1); print dec " " $0 }' /tmp/input
69 0x45 aaa 333
80 0x50 dd 33
4 0x4 bbbb 444
1110 0x456 cc 22
5 0x5 eee 1111
ステップ2:最初のフィールドの行を数字でソートします。
$ gawk --non-decimal-data '{ dec = sprintf("%d", $1); print dec " " $0 }' /tmp/input | sort -n -k 1
4 0x4 bbbb 444
5 0x5 eee 1111
69 0x45 aaa 333
80 0x50 dd 33
1110 0x456 cc 22
ステップ3:最初の列を削除します。
$ gawk --non-decimal-data '{ dec = sprintf("%d", $1); print dec " " $0 }' /tmp/input | sort -n -k 1 | cut -f2- -d' '
0x4 bbbb 444
0x5 eee 1111
0x45 aaa 333
0x50 dd 33
0x456 cc 22
答え4
sort -g
16進値を並べ替えることができます。0x
プレフィックスが必要です。
awk '{ $3 = "0x" $3; print }' sample.txt |
sort -g -k3 |
awk '{ $3 = gensub(/^0x/, "", 1, $3); print }'
0x
3列目に追加する前に- 汎用数値ソートオプションを使用して3番目の列に基づいてソート
0x
3番目の列から削除