web-dev-qa-db-ja.com

16進数値で並べ替え

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進数に変換します(大文字と小文字の16進数が必要で、0x接頭辞なしで、大文字と小文字が一致します)。次に、列を結合、並べ替え、分割します。

14
stefan

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ブロックでは、 Schwartzian transform を使用します:

    • @hの各要素を使用して、匿名配列を作成し、行全体($_->[1]@hの各配列refの2番目の要素)と比較する16進値hex($_->[0])]

    • 16進値$a->[1] <=> $b->[1]に基づいて配列の上をソートします

    • ソートされた配列map { $_->[0] }の各配列refの最初の要素を取得し、結果を出力します。

更新

シュワルツ変換を使用せずに@Joseph Rの提案を使用します。

$ Perl -anle '
    Push @h, [hex($F[-1]),$_];
    END {
        print $_->[1] for
            sort { $a->[0] <=> $b->[0] } @h;
    }
' file

更新2

ステファンのコメントを読んだ後、これはdirectを呼び出すことができると思います:

$ 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
5
cuonglm

このサンプルデータを使用します。

1 hdh d12
2 ukr 9f
3 ezh ae
4 jjk 7
5 hhf 25

アイデアは、10進形式の並べ替えフィールドを使用して、このデータの新しいバージョンを作成することです。つまりawkはそれを変換し、各行の前に付加し、結果をソートし、最後のステップとして、追加されたフィールドを削除します。

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
6
Hauke Laging

から適応: http://www.unix.com/302548935-post6.html?s=b4b6b3ed50b6831717f6429113302ad6

:file-to-sort:

6F993B
954B29
A23F2F
BFA91D
C68C15
8F322F
5A6D40
6D512C
9D9D63
B4B823
A0641C
A79716
A18518

コマンド:

awk '{printf("%050s\t%s\n", toupper($0), $0)}' file-to-sort | LC_COLLATE=C sort -k1,1 | cut -f2

出力:

C68C15
BFA91D
B4B823
A79716
A23F2F
A18518
A0641C
9D9D63
954B29
8F322F
6F993B
6D512C
5A6D40

--toupper($ 0)は小文字を「アップグレード」するため、最初にソートされます(ただし、それが必要かどうかはわかりませんか?)

1
r_alex_hall

入力

$ cat /tmp/input
0x45 aaa 333
0x50 dd 33
0x4 bbbb 444
0x456 cc 22
0x5 eee 1111

1つのライナーを並べ替える

$ 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
1
Arun Saha