हेक्स मूल्य के आधार पर छाँटें


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 और सभी समान लंबाई के साथ घूर रहे हैं? अपर / लोअरकेस का कोई मिश्रण नहीं? यदि हाँ, तो स्ट्रिंग्स के रूप में व्याख्या करने पर उन्हें ठीक करना चाहिए। शायद आप हमें कुछ उदाहरण डेटा दिखा सकते हैं?

@ यति: दुर्भाग्य से, नहीं।
स्टीफन

जवाबों:


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ब्लॉक, हम का उपयोग Schwartzian को बदलने :

    • प्रत्येक तत्व के साथ @h, एक अनाम सरणी बनाएं, जिसमें पूरी पंक्ति ( $_->[1]प्रत्येक सरणी का दूसरा तत्व Ref @h) और तुलनात्मक रूप से हेक्स मान समाहित हैhex($_->[0])]

    • हेक्स मान पर सरणी आधार के ऊपर क्रमबद्ध करें $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

अपडेट २

स्टीफन की टिप्पणी पढ़ने के बाद, मुझे लगता है कि यह कॉल कर सकता है 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ऑपरेटर शायद ही महंगा एक Schwartzian वारंट के लिए पर्याप्त है, है ना?
जोसेफ आर।

@ जोसेफ।: हो सकता है, लेकिन एक श्वार्ट्ज़ियन अधिक लचीला और सभी मामलों में काम करता है। मुझे लगता है कि प्रसंस्करण के दौरान हम हेक्स मान की गणना करके एक और समाधान कर सकते हैं, जल्द ही मेरे जवाब को अपडेट कर देंगे।
congonglm

शांत समाधान। पता नहीं इस पैटर्न का एक नाम था: सजाने-सॉर्ट-अघोषित। ऊपर मेरी टिप्पणी देखें।
स्टीफन

@stefan: मेरा अद्यतन उत्तर देखें।
16

@Gnouc: हाँ, आपका दूसरा अपडेट निश्चित रूप से डायरेक्ट wrt के रूप में योग्य है। मेरी प्रारंभिक कल्पना।
स्टेफान

6

मैं इस उदाहरण डेटा का उपयोग करता हूं:

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

इस डेटा को दशमलव रूप में सॉर्ट फ़ील्ड के साथ एक नया संस्करण बनाने का विचार है। Ie 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
धन्यवाद, बहुत अच्छा समाधान। क्षमा करें कि मैंने पहले अपना संपादन पोस्ट नहीं किया था, यह कट + पेस्ट का उपयोग करके एक समान दृष्टिकोण का अनुसरण करता है। मैं एक और अधिक प्रत्यक्ष समाधान के लिए उम्मीद कर रहा था हालांकि ...
स्टीफन

@stefan "डायरेक्ट" के रूप में क्या मायने रखता है? क्या समाधान का उपयोग करना है sort?
जोसेफ आर।

@ जोसेफ "सीधे" के रूप में क्या मायने रखता है? सही सवाल है। मूल रूप से अब तक सभी समाधान (Hauke's, Gnouc के नीचे, और मेरा) कुछ ऐसा ही करते हैं: हेक्स मान को डिकोड करें, लाइनों को परिणाम संलग्न करें, इसे सॉर्ट करें, और इसे हटा दें। मैं सजा-तरह-अघोषित पैटर्न का उपयोग नहीं करने के लिए कुछ ढूंढ रहा था । दोनों समाधान मेरे लिए बेहतर हैं, एक पाइप लाइन में उस तीखे काम में। मैंने इसे चुना है क्योंकि मैं व्यक्तिगत रूप से इस तरह के कार्य के लिए पर्ल की तुलना में awk (छोटा हथौड़ा) का उपयोग करूंगा।
स्टीफन

मैंने Gnouc के दूसरे अपडेट के कारण, नीचे # 3 के उत्तर के लिए अपनी पसंद को स्थानांतरित कर दिया है।
स्टेफान

1

से अनुकूलित: http://www.unix.com/302548935-post6.html?s=b4b6b3ed50b683171717646429113302ad6

: फ़ाइल-टू-तरह:

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 Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.