сортувати за шістнадцятковим значенням


14

Використовуючи coreutils sort, як я можу впорядкувати числове значення за шістнадцятковим значенням (полем)? Я чекав чогось за принципом

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

Пояснення

  • Під час обробки файлу ми створюємо масив масиву @h, кожен його елемент є посиланням на масив [$F[-1],$_], причому перший елемент - це шістнадцяте значення для порівняння, а другий елемент - це весь рядок.

  • У ENDблоці ми використовуємо перетворення Шварца :

    • З кожним елементом створення @h, створюйте анонімний масив, містить увесь рядок ( $_->[1]другий елемент кожного масиву, який посилається @h) та шістнадцяткове значення для порівнянняhex($_->[0])]

    • Сортувати над базою масиву за шістнадцятковим значенням $a->[1] <=> $b->[1]

    • Отримайте перший елемент ref кожного масиву у відсортованому масиві, map { $_->[0] } після чого надрукуйте результат.

Оновлення

З пропозицією @ Джозефа Р, не використовуючи Трансформацію Шварца:

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

Оновлення 2

Прочитавши коментар stefan, я думаю, що це може зателефонувати 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Оператор навряд чи досить дорого , щоб виправдати Шварц, чи не так?
Джозеф Р.

@JosephR .: Можливо, але Швартзян є більш гнучким і працює у будь-якому випадку. Я думаю, що ми можемо мати інше рішення, обчисливши шістнадцяткове значення під час обробки, незабаром оновить мою відповідь.
cuonglm

Прохолодний розчин. Не знав, що цей візерунок мав назву: прикрашати-сортувати-неприміряти. Дивіться мій коментар вище.
стефан

@stefan: дивіться мою оновлену відповідь.
cuonglm

@Gnouc: так, ваше 2-е оновлення остаточно кваліфікується як прямий wrt. моя початкова уява.
stefan

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?
Джозеф Р.

@ Джозеф "Що вважається" прямим "?" правильне питання. В основному всі рішення досі (Hauke, Gnouc's нижче та mine) роблять щось подібне: розшифровують шістнадцяткове значення, додають результат до рядків, сортують за ним та видаляють. Я шукав щось, не використовуючи шаблон прикрасити-сортувати-непримітно . Обидва рішення перевершують моє, оскільки вони працюють в трубопроводі. Я вибрав цей, тому що я особисто для цього виду використовував би awk (менший молоток), ніж Perl.
стефан

Я змінив свій вибір відповіді на номер 3 нижче, через друге оновлення Gnouc.
stefan

1

адаптовано з: 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

- де тапер ($ 0) "оновлює" малі літери, щоб вони сортували спочатку (не впевнені, що це потрібно?)


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: Додайте новий перший стовпець із десятковим поданням шістнадцяткового числа.

$ 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.