onaltılık değere göre sırala


14

Coreutils kullanarak sort, nasıl onaltılı bir değere (alan) sayısal olarak sıralayabilirim? Boyunca bir şeyler bekliyordum

sort -k3,3x file_to_sort

ancak böyle bir xmevcut değildir.

Edit: Şimdiye kadar geldi en iyi çözüm:

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

burada cut -d' ' -f3arama alanını yalıtır (bu -k3,3- bu elbette değişebilir) ve bcondalığa dönüştürme yapar ( 0xönek olmadan büyük / küçük harf gerektirir , benim durumumla eşleşir). Sonra sütunları birleştirir, sıralar ve bölerim.


-k3,3? 0x ile bakan hex nubers ve aynı uzunlukta mi? Büyük / küçük harf karışımı yok mu? Evet ise, dize olarak yorumlandığında doğru sıralama yapmalıdırlar. Belki bize bazı örnek veriler gösterebilirsiniz?

@yeti: Maalesef hayır.
— stefan

Yanıtlar:


5

Bir çözüm 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

açıklama

  • Dosya işlenirken, bir dizi dizisi @holuştururuz, öğesinin her biri bir dizi başvurusudur [$F[-1],$_], ilk öğe karşılaştırılacak onaltılık değerdir ve ikinci öğe tüm satırdır.

  • In ENDblokta, kullandığımız Schwartzian dönüşümü :

    • Her bir elemanı ile @hanonim dizi oluşturmak, bütün çizgi (içerir $_->[1], her bir dizi ref ikinci elemanı @h) ve karşılaştırma hex değerihex($_->[0])]

    • Onaltılık değerde dizi tabanının üstünde sırala $a->[1] <=> $b->[1]

    • Her dizinin ilk elemanını sıralı dizide al map { $_->[0] } ve sonucu yazdır.

Güncelleme

Schwartz Dönüşümünü kullanmadan @Joseph R'nin önerisiyle:

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

Güncelleme 2

Stefan'ın yorumunu okuduktan sonra, bunun şöyle diyebileceğini düşünüyorum 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 ama neden sadece: print for sort { hex $a->[-1] <=> hex $b->[-1] } @h? hexOperatör bir Schwartzian gerektirecek pek pahalı yeterince değil mi?
— Joseph R.

@JosephR .: Belki, ama bir Schwartzçı daha esnektir ve her durumda çalışır. Sanırım işleme sırasında onaltılık değeri hesaplayarak başka bir çözüm bulabiliriz, yakında cevabımı güncelleyeceğim.
— cuonglm

Serin çözüm. Bu modelin bir adı olduğunu bilmiyordum: decorate-sort-undecorate. Yukarıdaki yorumuma bakın.
— stefan

@ stefan: güncellenmiş cevabımı görün.
— cuonglm

@Gnouc: evet, 2. Güncellemeniz kesinlikle doğrudan wrt olarak nitelendirilir. ilk hayal gücüm.
— stefan

6

Bu örnek verileri kullanıyorum:

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

Amaç, bu verilerin ondalık formda sıralama alanı ile yeni bir sürümünü oluşturmaktır. Yani awkdönüştürür, her satıra ekler, sonuç sıralanır ve son adım olarak eklenen alan kaldırılır:

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

Bu çıktıyla sonuçlanan:

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

1
Teşekkürler, oldukça güzel bir çözüm. Düzenlememi daha önce göndermediğim için üzgünüm, cut + paste kullanarak benzer bir yaklaşım izliyor. Yine de daha doğrudan bir çözüm umuyordum ...
— Stefan

@stefan "Doğrudan" olarak sayılan nedir? Çözüm kullanmak zorunda sortmı?
— Joseph R.

@Joseph “Ne“ direkt ”olarak sayılır?” doğru soru. Temel olarak şu ana kadar tüm çözümler (Hauke, aşağıdaki Gnouc ve benimki) benzer bir şey yapar: Onaltılık değeri kodunu çöz, sonucu satırlara ekle, sırala ve kaldır. Ben dekore-sıralama-bezemesiz desen kullanarak bir şey arıyordum . Her iki çözüm de bir boru hattında bu işte benimkinden daha üstündür. Bunu seçtim çünkü kişisel olarak bu tür bir görev için Perl'den daha awk (küçük çekiç) kullanmayı tercih ederim.
— stefan

Cevap seçimimi Gnouc'un ikinci güncellemesi nedeniyle aşağıdaki # 3'e taşıdım.
— stefan

1

uyarlanmış: http://www.unix.com/302548935-post6.html?s=b4b6b3ed50b6831717f6429113302ad6

: Dosya-to-sort:

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

Komut:

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

Çıktı:

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

- toupper ($ 0) küçük harfleri ilk sırada sıralayacakları şekilde "yükseltir" (bunun gerekli olduğundan emin değil misiniz?)


1

Giriş

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

Bir astarı sıralama

$ 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

Adım adım sıralama

Adım 1: Onaltılık sayının ondalık gösterimi ile yeni bir ilk sütun ekleyin.

$ 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

Adım 2: İlk alanda çizgileri sayısal olarak sıralayın.

$ 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. Adım: İlk sütunu kaldırın.

$ 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.