16진수 값으로 정렬

16진수 값으로 정렬

coreutils를 사용하여 sort16진수 값(필드)을 기준으로 숫자를 정렬하는 방법은 무엇입니까? 나는 이런 것을 기대하고 있었다

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수 있음) bc10진수로 변환합니다(대소 0x문자를 일치시키려면 접두어 없이 대문자 16진수가 필요함). 그런 다음 열을 연결하고 정렬하고 분할합니다.

최소 샘플 입력:

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

예상 출력( hex세 번째 열로 정렬된 파일):

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

아이디어는 십진수 형식의 정렬 필드를 사용하여 이 데이터의 새 버전을 생성하는 것입니다. 즉, awk1 변환하여 각 행의 앞에 추가하고 결과를 정렬한 다음 마지막 단계에서 추가된 필드를 제거합니다.

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 이는 GNU awk기능을 가정합니다 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진수 값이고, 두 번째 요소는 전체 라인입니다.

  • END우리가 사용하는 블록 에서는슈워츠 변환:

    • 각 요소를 사용하여 @h전체 행( $_->[1]각 배열 참조의 두 번째 요소 @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 -g16진수 값을 정렬할 수 있습니다. 0x접두사 가 필요합니다 .

awk '{ $3 = "0x" $3; print }' sample.txt |
 sort -g -k3 |
 awk '{ $3 = gensub(/^0x/, "", 1, $3); print }'
  1. 0x세 번째 열에 추가하기 전에
  2. 범용 숫자 정렬 옵션을 사용하여 세 번째 열을 기준으로 정렬
  3. 0x세 번째 열에서 삭제

관련 정보