classificar por valor hexadecimal

13

Usando o coreutils sort , como posso classificar numericamente por um valor hexadecimal (campo)? Eu estava esperando algo ao longo das linhas de

sort -k3,3x file_to_sort

no entanto, esse x não existe.

Edite: A melhor solução que encontrei até agora é:

{ echo ibase=16; cut -d' ' -f3 file_to_sort; } |
  bc | paste -d: - file_to_sort | sort -t: -k1,1n | cut -d: -f2-

em que cut -d' ' -f3 isola o campo de pesquisa (isso é -k3,3 - isso pode variar, é claro) e bc faz conversão em decimal (requer maiúscula hexadecimal, sem 0x prefixo, correspondendo a minha caso). Então eu participo, classifico e separo colunas.

    
por stefan 29.06.2014 / 16:32

4 respostas

4

Uma solução em 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

Explicação

  • Durante o processamento do arquivo, criamos uma matriz da matriz @h , cada elemento é uma referência da matriz [$F[-1],$_] , com o primeiro elemento é o valor hexadecimal a ser comparado e o segundo elemento é toda a linha .

  • No bloco END , usamos Transformação de Schwartzian :

    • Com cada elemento de @h , crie uma matriz anônima, contém a linha inteira ( $_->[1] o segundo elemento de cada matriz ref em @h ) e o valor hexadecimal para comparar hex($_->[0])]

    • Classifique acima da base da matriz no valor hexadecimal $a->[1] <=> $b->[1]

    • Pegue o primeiro elemento de cada matriz ref na matriz classificada map { $_->[0] } e imprima o resultado.

Atualizar

Com a sugestão de @Joseph R, sem usar o Schwartzian Transform:

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

Atualização 2

Depois de ler o comentário do stefan, acho que isso pode chamar 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
    
por 29.06.2014 / 18:09
6

Eu uso este exemplo de dados:

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

A ideia é criar uma nova versão desses dados com o campo de classificação em formato decimal. Ou seja awk converte-o, adiciona-o a cada linha, o resultado é ordenado e, como último passo, o campo adicionado é removido:

awk '{val="0x" $3; sub("^0x0x","0x",val); print strtonum(val),$0 ;}' file | 
  sort -n | 
  sed 's/^[^ ]* //'

O que resulta nesta saída:

4 jjk 7
5 hhf 25
2 ukr 9f
3 ezh ae
1 hdh d12
    
por 29.06.2014 / 16:57
0

adaptado de: link

: file-to-sort:

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

Comando:

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

Saída:

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

- onde o toupper ($ 0) "atualiza" as letras minúsculas para que elas sejam classificadas primeiro (não tenho certeza se é necessário?)

    
por 23.04.2017 / 04:03
0

Entrada

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

Classificando um revestimento

$ 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

Classificando passo a passo

Passo 1: Adicione uma nova primeira coluna com a representação decimal do número hexadecimal.

$ 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

Etapa 2: classifique as linhas numericamente no primeiro campo.

$ 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

Etapa 3: remova a primeira coluna.

$ 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
    
por 27.07.2017 / 00:49