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.