16 진수 값으로 정렬


14

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진수로 변환을한다 (하지 않고, 대문자 진수를 필요로 0x내 경우 일치하는 접두사). 그런 다음 열을 결합, 정렬 및 분할합니다.


-k3,3? 0x와 같은 길이의 헥사 숫자가 있습니까? 대소 문자가 혼합되어 있지 않습니까? 그렇다면 문자열로 해석 될 때 올바르게 정렬해야합니다. 예시 데이터를 보여 주시겠습니까?

@yeti : 불행히도.
스테판

답변:


5

의 해결책 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

설명

  • 파일을 처리하는 동안 array의 배열을 만들고 @h각 요소는 배열 참조 [$F[-1],$_]이며 첫 번째 요소는 16 진수 값이고 두 번째 요소는 전체 줄입니다.

  • 에서 END블록, 우리는 사용 찌언 변환 :

    • 의 각 요소를 @h사용하여 익명 배열을 만들고 전체 행 ( $_->[1]각 배열의 두 번째 요소 참조 @h)과 16 진수 값을 포함합니다.hex($_->[0])]

    • 16 진수 값을 기준으로 배열 기준으로 정렬 $a->[1] <=> $b->[1]

    • 정렬 된 배열에서 각 배열 참조의 첫 번째 요소를 map { $_->[0] } 가져온 다음 결과를 인쇄하십시오.

최신 정보

Schwartzian Transform을 사용하지 않고 @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

+1 그러나 왜 안되는가 : print for sort { hex $a->[-1] <=> hex $b->[-1] } @h? hex연산자는 찌언 보증하는 거의 비싼만큼, 그렇지 않나요?
Joseph R.

@JosephR .: 아마도 Schwartzian은 더 유연하고 모든 경우에 작동합니다. 처리하는 동안 16 진수 값을 계산하여 다른 솔루션을 가질 수 있다고 생각합니다. 곧 답변을 업데이트 할 것입니다.
cuonglm

멋진 솔루션. 이 패턴의 이름을 알지 못했습니다 : decorate-sort-undecorate. 위의 내 의견을 참조하십시오.
스테판

@ stefan : 업데이트 된 답변을 참조하십시오.
cuonglm 2016 년

@Gnouc : 예. 두 번째 업데이트는 직접 wrt로 자격이 있습니다. 나의 초기 상상력.
스테판

6

이 예제 데이터를 사용합니다.

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

아이디어는 정렬 필드를 십진 형식으로이 데이터의 새 버전을 작성하는 것입니다. 즉 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

1
정말 멋진 솔루션입니다. 편집 내용을 이전에 게시하지 않아 죄송합니다. cut + paste를 사용하는 비슷한 방법을 따릅니다. 나는 더 직접적인 해결책을 기대하고 있었지만 ...
stefan

@stefan "직접"으로 간주되는 것은 무엇입니까? 솔루션을 사용해야 sort합니까?
Joseph R.

@Joseph““직접적인”것으로 간주되는 것은? 올바른 질문입니다. 기본적으로 지금까지의 모든 솔루션 (Hauke ​​'s, Gnouc 's 및 내)은 16 진수 값을 디코딩하고 결과를 줄에 첨부하고 정렬하여 제거합니다. decorate-sort-undecorate 패턴을 사용하지 않는 것을 찾고있었습니다 . 두 솔루션 모두 파이프 라인에서 작동한다는 점에서 내 솔루션보다 우수합니다. 개인적으로 이런 종류의 작업에 Perl보다 awk (작은 망치)를 사용하기 때문에 이것을 선택했습니다.
스테판

나는 Gnouc의 두 번째 업데이트 때문에 아래의 # 3에 대한 답변 선택을 옮겼습니다.
스테판

1

입력

$ 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

0

적응 : http://www.unix.com/302548935-post6.html?s=b4b6b3ed50b6831717f6429113302ad6

: 파일 정렬

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)는 소문자를 "업그레이드"하여 먼저 정렬합니다 (필요하지는 않습니까?)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.