मैं सीमांकित आइटमों की एक पंक्ति को संख्यात्मक रूप से कैसे सॉर्ट कर सकता हूं?


11

मेरे पास एक संख्या (या कई पंक्तियों) की संख्या है जो एक मनमाना चरित्र द्वारा सीमांकित है। UNIX उपकरण क्या मैं प्रत्येक लाइन के आइटम को संख्यात्मक रूप से सॉर्ट करने के लिए उपयोग कर सकता हूं, सीमांकक को बनाए रखता है?

उदाहरणों में शामिल:

  • संख्याओं की सूची; इनपुट: 10 50 23 42; सॉर्ट किया गया:10 23 42 50
  • आईपी ​​पता; इनपुट: 10.1.200.42; सॉर्ट किया गया:1.10.42.200
  • सीएसवी; इनपुट: 1,100,330,42; सॉर्ट किया गया:1,42,100,330
  • पाइप-सीमांकित; इनपुट: 400|500|404; सॉर्ट किया गया:400|404|500

चूंकि सीमांकक मनमाना है, इसलिए अपने चयन के एकल-चरित्र परिसीमन का उपयोग करके उत्तर देने (या विस्तार) के लिए स्वतंत्र महसूस करें।


8
आपको इसे कोडगोल्फ :)
ivanivan

1
इसी तरह का एक सवाल यह भी है कि मैं इसके लिंक को वर्णमाला के भीतर वर्णमाला के शब्दों
α atsнιη

बस एक संकेत है जो cutअपने -dविकल्प के साथ मनमाने delimiters का समर्थन करता है।
ओलेग लोबाचेव

कृपया यह स्पष्ट करें कि क्या DSV s के वे चार उदाहरण एक ही फाइल में हैं, या चार अलग-अलग फाइलों के नमूने हैं।
अगस्त

2
कुछ अन्य टिप्पणियों को देखकर: सीमांकक मनमाना है, लेकिन इनपुट में लगातार उपयोग किया जाएगा। डेटा प्रोड्यूसर के हिस्से पर ऐसी खुफिया जानकारी मानें कि वे कॉमा का उपयोग सीमांकक के रूप में और डेटा में 4,325 comma 55 comma 42,430नहीं करेंगे (उदाहरण के लिए, नहीं होगा, न ही 1.5 period 4.2)।
जेफ स्कालर

जवाबों:


12

आप इसे प्राप्त कर सकते हैं:

tr '.' '\n' <<<"$aline" | sort -n | paste -sd'.' -

अपने परिसीमन के साथ डॉट्स बदलें .। डुप्लिकेट को निकालने के लिए ऊपर दिए गए आदेश में
जोड़ें ।-usort


या gawk( GNU awk ) के साथ हम कई लाइनों को संसाधित कर सकते हैं जबकि ऊपर भी बढ़ाया जा सकता है:

gawk -v SEP='*' '{ i=0; split($0, arr, SEP); 
    while ( ++i<=asort(arr) ){ printf("%s%s", i>1?SEP:"", arr[i]) }; 
        print "" 
}' infile

अपने परिसीमन के साथ *क्षेत्र विभाजक के रूप में बदलें ।SEP='*'


नोट:
आपको किसी भी संख्या के वर्ग (पूर्णांक, फ्लोट, वैज्ञानिक, हेक्साडेसिमल, आदि) को संभालने -g, --general-numeric-sortके sortबजाय विकल्प का उपयोग करने की आवश्यकता हो सकती है -n, --numeric-sort

$ aline='2e-18,6.01e-17,1.4,-4,0xB000,0xB001,23,-3.e+11'
$ tr ',' '\n' <<<"$aline" |sort -g | paste -sd',' -
-3.e+11,-4,2e-18,6.01e-17,1.4,23,0xB000,0xB001

में awkकोई जरूरत परिवर्तन, यह अभी भी उन से निपटने होगा।


10

perlएक स्पष्ट संस्करण का उपयोग करना ; डेटा को विभाजित करें, इसे सॉर्ट करें, इसे फिर से जोड़ दें।

सीमांकक को दो बार (एक बार splitऔर एक बार join) सूचीबद्ध करने की आवश्यकता है

उदाहरण के लिए a ,

perl -lpi -e '$_=join(",",sort {$a <=> $b} split(/,/))'

इसलिए

echo 1,100,330,42 | perl -lpi -e '$_=join(",",sort {$a <=> $b} split(/,/))'
1,42,100,330

चूंकि splitएक रेगेक्स है, चरित्र को उद्धृत करने की आवश्यकता हो सकती है:

echo 10.1.200.42 | perl -lpi -e '$_=join(".",sort {$a <=> $b} split(/\./))'
1.10.42.200

-aऔर -Fविकल्पों का उपयोग करके , विभाजन को हटाना संभव है। -pलूप के साथ , पहले की तरह और परिणामों को सेट करें $_, जो स्वचालित रूप से प्रिंट करेगा:

perl -F'/\./' -aple '$_=join(".", sort {$a <=> $b} @F)'

4
आप उपयोग -lकरने के बजाय विकल्प का उपयोग कर सकते हैं chomp। यह भी मुद्रण पर newline वापस जोड़ता है। बंटवारे वाले हिस्से के लिए भी -a(साथ -F) देखें ।
स्टीफन चेजलस

1
साथ -lऔर -F:, तो यह और भी बेहतर होता हैperl -F'/\./' -le 'print join(".", sort {$a <=> $b} @F)'
muru

@ स्टीफनचैजेलस -lविकल्प के लिए धन्यवाद ; मैं चूक गया!
स्टीफन हैरिस

1
@ एमुरु ने -Fमूल रूप से ध्वज का उपयोग नहीं किया क्योंकि यह सभी संस्करणों में ठीक से काम नहीं करता है (जैसे कि CentOS 7 में आपकी लाइन - प्रति 5.16.3 - खाली आउटपुट देता है, हालांकि यह डेबियन 9 पर ठीक काम करता है)। लेकिन -pइसके साथ संयुक्त एक छोटा सा परिणाम देता है, इसलिए मैंने उत्तर के विकल्प के रूप में इसे जोड़ा। दिखा रहा है कि कैसे -Fइस्तेमाल किया जा सकता है। धन्यवाद!
स्टीफन हैरिस

2
@StephenHarris ऐसा इसलिए है क्योंकि पर्ल के नए संस्करण स्वचालित रूप से जोड़ते हैं -aऔर -nजब -Fउपयोग किया जाता है और -nजब उपयोग किया जाता है तो विकल्प -a... तो बस बदल -leदें-lane
Sundeep

4

स्टीफन हैरिस के जवाब में पायथन और एक समान विचार का उपयोग करना :

python3 -c 'import sys; c = sys.argv[1]; sys.stdout.writelines(map(lambda x: c.join(sorted(x.strip().split(c), key=int)) + "\n", sys.stdin))' <delmiter>

तो कुछ इस तरह:

$ cat foo
10.129.3.4
1.1.1.1
4.3.2.1
$ python3 -c 'import sys; c = sys.argv[1]; sys.stdout.writelines(map(lambda x: c.join(sorted(x.strip().split(c), key=int)) + "\n", sys.stdin))' . < foo
3.4.10.129
1.1.1.1
1.2.3.4

अफसोस की बात है कि आई / ओ मैन्युअल रूप से करने के लिए यह पर्ल संस्करण की तुलना में बहुत कम सुरुचिपूर्ण बनाता है।


3

बैश स्क्रिप्ट:

#!/usr/bin/env bash

join_by(){ local IFS="$1"; shift; echo "$*"; }

IFS="$1" read -r -a tokens_array <<< "$2"
IFS=$'\n' sorted=($(sort -n <<<"${tokens_array[*]}"))
join_by "$1" "${sorted[@]}"

उदाहरण:

$ ./sort_delimited_string.sh "." "192.168.0.1"
0.1.168.192

पर आधारित


3

खोल

उच्च स्तरीय भाषा लोड होने में समय लगता है।
कुछ पंक्तियों के लिए, शेल स्वयं एक समाधान हो सकता है।
हम बाहरी कमांड sort, और कमांड का उपयोग कर सकते हैं tr। एक लाइनों को छांटने में काफी कुशल है और दूसरा एक सीमांकक को न्यूलाइन्स में बदलने के लिए प्रभावी है:

#!/bin/bash
shsort(){
           while IFS='' read -r line; do
               echo "$line" | tr "$1" '\n' |
               sort -n   | paste -sd "$1" -
           done <<<"$2"
    }

shsort ' '    '10 50 23 42'
shsort '.'    '10.1.200.42'
shsort ','    '1,100,330,42'
shsort '|'    '400|500|404'
shsort ','    '3 b,2       x,45    f,*,8jk'
shsort '.'    '10.128.33.6
128.17.71.3
44.32.63.1'

<<<केवल उपयोग की वजह से इसे बैश की जरूरत है । यदि वह यहाँ-डॉक के साथ बदल दिया जाता है, तो समाधान पॉज़िक्स के लिए मान्य है।
यह टैब, रिक्त स्थान या खोल ग्लोब पात्रों के साथ खेतों को सॉर्ट करने में सक्षम है ( *, ?, [)। प्रत्येक पंक्ति को छांटा जा रहा है, क्योंकि नई लाइनें नहीं हैं।

फ़ाइल नाम संसाधित करने और इसे कॉल <<<"$2"करने के <"$2"लिए बदलें :

shsort '.'    infile

सीमांकक पूरी फ़ाइल के लिए समान है। यदि वह एक सीमा है, तो उस पर सुधार किया जा सकता है।

हालाँकि सिर्फ 6000 लाइनों वाली एक फाइल को प्रोसेस होने में 15 सेकंड का समय लगता है। सच में, शेल फाइलों को प्रोसेस करने का सबसे अच्छा साधन नहीं है।

awk

कुछ लाइनों (कुछ 10 से अधिक) से अधिक के लिए वास्तविक प्रोग्रामिंग भाषा का उपयोग करना बेहतर है। एक अजीब समाधान हो सकता है:

#!/bin/bash
awksort(){
           gawk -v del="$1" '{
               split($0, fields, del)
               l=asort(fields)
               for(i=1;i<=l;i++){
                   printf( "%s%s" , (i==0)?"":del , fields[i] )
               }
               printf "\n"
           }' <"$2"
         }

awksort '.'    infile

ऊपर बताई गई समान 6000 लाइनों वाली फ़ाइल के लिए केवल 0.2 सेकंड लगते हैं।

समझें कि शेल चर के अंदर लाइनों के <"$2"लिए फ़ाइलों को वापस बदला जा सकता है <<<"$2"

पर्ल

सबसे तेज़ समाधान पर्ल है।

#!/bin/bash
perlsort(){  perl -lp -e '$_=join("'"$1"'",sort {$a <=> $b} split(/['"$1"']/))' <<<"$2";   }

perlsort ' '    '10 50 23 42'
perlsort '.'    '10.1.200.42'
perlsort ','    '1,100,330,42'
perlsort '|'    '400|500|404'
perlsort ','    '3 b,2       x,45    f,*,8jk'
perlsort '.'    '10.128.33.6
128.17.71.3
44.32.63.1'

यदि आप फ़ाइल परिवर्तन <<<"$a"को बस क्रमबद्ध करना चाहते हैं "$a"और -iफ़ाइल संस्करण को "स्थान पर" बनाने के लिए पर्ल विकल्पों में जोड़ें :

#!/bin/bash
perlsort(){  perl -lpi -e '$_=join("'"$1"'",sort {$a <=> $b} split(/['"$1"']/))' "$2"; }

perlsort '.' infile; exit

2

sedIP पते के ऑक्टेट को सॉर्ट करने के लिए उपयोग करना

sedएक अंतर्निहित sortफ़ंक्शन नहीं है, लेकिन यदि आपका डेटा पर्याप्त रूप से सीमा में सीमित है (जैसे कि आईपी पते के साथ), तो आप एक सीड स्क्रिप्ट उत्पन्न कर सकते हैं जो मैन्युअल रूप से एक साधारण बुलबुला प्रकार लागू करता है । बुनियादी तंत्र आसन्न संख्याओं के लिए देखना है जो आउट-ऑफ-ऑर्डर हैं। यदि संख्या क्रम से बाहर हैं, तो उन्हें स्वैप करें।

sedओकटेट के पहले दो जोड़े के लिए एक (एक अनुगामी सीमांकक के लिए मजबूर कर तीसरे ओकटेट के अंत चिह्नित करने के लिए उपस्थित होना), और एक: स्क्रिप्ट ही बाहर के आदेश संख्या की प्रत्येक जोड़ी के लिए दो खोजें-और-स्वैप आदेशों शामिल ऑक्टेट्स की तीसरी जोड़ी के लिए दूसरा (ईओएल के साथ अंत)। यदि स्वैप होते हैं, तो प्रोग्राम शाखाएं स्क्रिप्ट के शीर्ष पर होती हैं, जो संख्याओं की तलाश में होती हैं जो आउट-ऑफ-ऑर्डर हैं। अन्यथा, यह बाहर निकलता है।

उत्पन्न स्क्रिप्ट भाग में है:

$ head -n 3 generated.sed
:top
s/255\.254\./254.255./g; s/255\.254$/254.255/
s/255\.253\./253.255./g; s/255\.253$/253.255/

# ... middle of the script omitted ...

$ tail -n 4 generated.sed
s/2\.1\./1.2./g; s/2\.1$/1.2/
s/2\.0\./0.2./g; s/2\.0$/0.2/
s/1\.0\./0.1./g; s/1\.0$/0.1/
ttop

यह हार्ड-कोड को परिसीमाक के रूप में उस अवधि तक पहुंचाता है, जिसे बचाना पड़ता है, अन्यथा यह नियमित अभिव्यक्ति सिंटैक्स के लिए "विशेष" होगा (किसी भी वर्ण की अनुमति)।

इस तरह की एक स्क्रिप्ट बनाने के लिए, यह लूप करेगा:

#!/bin/bash

echo ':top'

for (( n = 255; n >= 0; n-- )); do
  for (( m = n - 1; m >= 0; m-- )); do
    printf '%s; %s\n' "s/$n\\.$m\\./$m.$n./g" "s/$n\\.$m\$/$m.$n/"
  done
done

echo 'ttop'

उस स्क्रिप्ट के आउटपुट को किसी अन्य फ़ाइल में रीडायरेक्ट करें, कहते हैं sort-ips.sed

एक नमूना रन तब जैसा दिख सकता है:

ip=$((RANDOM % 256)).$((RANDOM % 256)).$((RANDOM % 256)).$((RANDOM % 256))
printf '%s\n' "$ip" | sed -f sort-ips.sed

जनरेटिंग स्क्रिप्ट पर निम्न भिन्नता शब्द सीमा मार्कर का उपयोग करती है \<और \>दूसरे प्रतिस्थापन की आवश्यकता से छुटकारा पाने के लिए। यह उत्पन्न स्क्रिप्ट के आकार को 1.3 एमबी से घटाकर सिर्फ 900 केबी के नीचे कर देता है और साथ ही साथ sedस्वयं के रन समय को भी कम करता है (मूल के लगभग 50% -75%, sedकार्यान्वयन के आधार पर क्या उपयोग किया जा रहा है):

#!/bin/bash

echo ':top'

for (( n = 255; n >= 0; --n )); do
  for (( m = n - 1; m >= 0; --m )); do
      printf '%s\n' "s/\\<$n\\>\\.\\<$m\\>/$m.$n/g"
  done
done

echo 'ttop'

1
एक दिलचस्प विचार है, लेकिन यह चीजों को थोड़ा जटिल करता है।
मैट अप

1
@ मैट यह बात है। किसी भी चीज को छांटना sedहास्यास्पद है, यही वजह है कि यह एक दिलचस्प चुनौती है।
Kusalananda

2

यहाँ कुछ बैश हैं जो अनुमान लगाते हैं

#!/bin/bash

delimiter="${1//[[:digit:]]/}"
if echo $delimiter | grep -q "^\(.\)\1\+$"
then
  delimiter="${delimiter:0:1}"
  if [[ -z $(echo $1 | grep "^\([0-9]\+"$delimiter"\([0-9]\+\)*\)\+$") ]]
  then
    echo "You seem to have empty fields between the delimiters."
    exit 1
  fi
  if [[ './\' == *$delimiter* ]]
  then
    n=$( echo $1 | sed "s/\\"$delimiter"/\\n/g" | sort -n | tr '\n' ' ' | sed -e "s/\\s/\\"$delimiter"/g")
  else
    n=$( echo $1 | sed "s/"$delimiter"/\\n/g" | sort -n | tr '\n' ' ' | sed -e "s/\\s/"$delimiter"/g")
  fi
  echo ${n%$delimiter}
  exit 0
else
  echo "The string does not consist of digits separated by one unique delimiter."
  exit 1
fi

यह बहुत कुशल और न ही साफ हो सकता है लेकिन यह काम करता है।

का उपयोग करें bash my_script.sh "00/00/18/29838/2"

जब एक ही सीमांकक का लगातार उपयोग नहीं किया जाता है या दो या दो से अधिक सीमांकक एक दूसरे का अनुसरण करते हैं तो एक त्रुटि होती है।

यदि प्रयुक्त सीमांकक एक विशेष वर्ण है तो यह बच जाता है (अन्यथा sedकोई त्रुटि देता है)।


यही कारण है कि प्रेरित इस
agc

2

यह उत्तर Q की गलतफहमी पर आधारित है, लेकिन कुछ मामलों में यह वैसे भी सही होता है। यदि इनपुट पूरी तरह से प्राकृतिक संख्या है , और इसमें केवल एक सीमांकक प्रति-पंक्ति है, (क्यू में नमूना डेटा के साथ), यह सही ढंग से काम करता है। यह उन पंक्तियों के साथ फाइलें भी संभालेगा, जिनमें से प्रत्येक का अपना सीमांकक है, जो कि जो कुछ पूछा गया था, उससे थोड़ा अधिक है।

यह शेल readमानक इनपुट से कार्य करता है, प्रत्येक लाइन पर विशिष्ट सीमांकक को खोजने के लिए POSIX पैरामीटर प्रतिस्थापन का उपयोग करता है , (संग्रहीत $d), और एक नई लाइन के साथ trबदलने के लिए उपयोग करता है और फिर उस लाइन के मूल सीमांकक को पुनर्स्थापित करता है:$d\nsort

sdn() { while read x; do
            d="${x#${x%%[^0-9]*}}"   d="${d%%[0-9]*}"
            x=$(echo -n "$x" | tr "$d" '\n' | sort -g | tr '\n' "$d")
            echo ${x%?}
        done ; }

ओपी में दिए गए डेटा पर लागू :

printf "%s\n" "10 50 23 42" "10.1.200.42" "1,100,330,42" "400|500|404" | sdn

आउटपुट:

10 23 42 50
1.10.42.200
1,42,100,330
400|404|500

किसी भी लाइन में परिसीमन सुसंगत होगा; सामान्य समाधान जो उपयोगकर्ता को सीमांकक घोषित करने की अनुमति देते हैं वे भयानक हैं, लेकिन उत्तर किसी भी परिसीमन को मान सकते हैं जो उन्हें समझ में आता है (एकल वर्ण और स्वयं संख्यात्मक डेटा में मौजूद नहीं है)।
जेफ स्कालर

2

मनमानी के लिए:

perl -lne '
  @list = /\D+|\d+/g;
  @sorted = sort {$a <=> $b} grep /\d/, @list;
  for (@list) {$_ = shift@sorted if /\d/};
  print @list'

जैसे इनपुट पर:

5,4,2,3
6|5,2|4
There are 10 numbers in those 3 lines

यह देता है:

2,3,4,5
2|4,5|6
There are 3 numbers in those 10 lines

0

यह किसी भी गैर-अंक (0-9) परिसीमन को संभालना चाहिए। उदाहरण:

x='1!4!3!5!2'; delim=$(echo "$x" | tr -d 0-9 | cut -b1); echo "$x" | tr "$delim" '\n' | sort -g | tr '\n' "$delim" | sed "s/$delim$/\n/"

आउटपुट:

1!2!3!4!5

0

के साथ perl:

$ # -a to auto-split on whitespace, results in @F array
$ echo 'foo baz v22 aimed' | perl -lane 'print join " ", sort @F'
aimed baz foo v22
$ # {$a <=> $b} for numeric comparison, {$b <=> $a} will give descending order
$ echo '1,100,330,42' | perl -F, -lane 'print join ",", sort {$a <=> $b} @F'
1,42,100,330

के साथ ruby, जो कुछ हद तक समान हैperl

$ # -a to auto-split on whitespace, results in $F array
$ # $F is sorted and then joined using the given string
$ echo 'foo baz v22 aimed' | ruby -lane 'print $F.sort * " "'
aimed baz foo v22

$ # (&:to_i) to convert string to integer
$ echo '1,100,330,42' | ruby -F, -lane 'print $F.sort_by(&:to_i) * ","'
1,42,100,330

$ echo '10.1.200.42' | ruby -F'\.' -lane 'print $F.sort_by(&:to_i) * "."'
1.10.42.200


कस्टम कमांड और केवल सीमांकक स्ट्रिंग (रेगेक्स नहीं) पास करना। काम करेगा अगर इनपुट में फ्लोटिंग डेटा भी है

$ # by default join uses value of $,
$ sort_line(){ ruby -lne '$,=ENV["d"]; print $_.split($,).sort_by(&:to_f).join' ; }

$ s='103,14.5,30,24'
$ echo "$s" | d=',' sort_line
14.5,24,30,103
$ s='10.1.200.42'
$ echo "$s" | d='.' sort_line
1.10.42.200

$ # for file input
$ echo '123--87--23' > ip.txt
$ echo '3--12--435--8' >> ip.txt
$ d='--' sort_line <ip.txt
23--87--123
3--8--12--435


के लिए कस्टम कमांड perl

$ sort_line(){ perl -lne '$d=$ENV{d}; print join $d, sort {$a <=> $b} split /\Q$d/' ; }
$ s='123^[]$87^[]$23'
$ echo "$s" | d='^[]$' sort_line 
23^[]$87^[]$123


आगे पढ़ना - मेरे पास पहले से ही पर्ल / रूबी वन-लाइनर्स की यह आसान सूची थी


0

जेफ के जवाब पर निम्नलिखित इस अर्थ में भिन्नता है कि यह एक sedस्क्रिप्ट बनाता है जो बबल सॉर्ट करेगा, लेकिन अपने स्वयं के उत्तर को वारंट करने के लिए पर्याप्त रूप से अलग है।

अंतर यह है कि ओ (एन ^ 2) मूल नियमित अभिव्यक्ति उत्पन्न करने के बजाय, यह ओ (एन) विस्तारित नियमित अभिव्यक्ति उत्पन्न करता है। परिणामी स्क्रिप्ट लगभग 15 KB बड़ी होगी। sedस्क्रिप्ट का रनिंग टाइम एक सेकंड के अंश में होता है (स्क्रिप्ट को जेनरेट करने में थोड़ा अधिक समय लगता है)।

यह डॉट्स द्वारा सीमांकित पॉजिटिव पूर्णांकों को क्रमबद्ध करने के लिए प्रतिबंधित है, लेकिन यह पूर्णांकों के आकार ( 255मुख्य लूप में वृद्धि ), या पूर्णांकों की संख्या तक सीमित नहीं है । delim='.'कोड में बदलाव करके परिसीमन को बदला जा सकता है ।

यह नियमित अभिव्यक्ति सही पाने के लिए मेरे सिर पर किया जाता है, इसलिए मैं दूसरे दिन के विवरण का वर्णन करना छोड़ दूंगा।

#!/bin/bash

# This function creates a extended regular expression
# that matches a positive number less than the given parameter.
lt_pattern() {
    local n="$1"  # Our number.
    local -a res  # Our result, an array of regular expressions that we
                  # later join into a string.

    for (( i = 1; i < ${#n}; ++i )); do
        d=$(( ${n: -i:1} - 1 )) # The i:th digit of the number, from right to left, minus one.

        if (( d >= 0 )); then
            res+=( "$( printf '%d[0-%d][0-9]{%d}' "${n:0:-i}" "$d" "$(( i - 1 ))" )" )
        fi
    done

    d=${n:0:1} # The first digit of the number.
    if (( d > 1 )); then
        res+=( "$( printf '[1-%d][0-9]{%d}' "$(( d - 1 ))" "$(( ${#n} - 1 ))" )" )
    fi

    if (( n > 9 )); then
        # The number is 10 or larger.
        res+=( "$( printf '[0-9]{1,%d}' "$(( ${#n} - 1 ))" )" )
    fi

    if (( n == 1 )); then
        # The number is 1. The only thing smaller is zero.
        res+=( 0 )
    fi

    # Join our res array of expressions into a '|'-delimited string.
    ( IFS='|'; printf '%s\n' "${res[*]}" )
}

echo ':top'

delim='.'

for (( n = 255; n > 0; --n )); do
    printf 's/\\<%d\\>\\%s\\<(%s)\\>/\\1%s%d/g\n' \
        "$n" "$delim" "$( lt_pattern "$n" )" "$delim" "$n"
done

echo 'ttop'

स्क्रिप्ट कुछ इस तरह दिखाई देगी:

$ bash generator.sh >script.sed
$ head -n 5 script.sed
:top
s/\<255\>\.\<(25[0-4][0-9]{0}|2[0-4][0-9]{1}|[1-1][0-9]{2}|[0-9]{1,2})\>/\1.255/g
s/\<254\>\.\<(25[0-3][0-9]{0}|2[0-4][0-9]{1}|[1-1][0-9]{2}|[0-9]{1,2})\>/\1.254/g
s/\<253\>\.\<(25[0-2][0-9]{0}|2[0-4][0-9]{1}|[1-1][0-9]{2}|[0-9]{1,2})\>/\1.253/g
s/\<252\>\.\<(25[0-1][0-9]{0}|2[0-4][0-9]{1}|[1-1][0-9]{2}|[0-9]{1,2})\>/\1.252/g
$ tail -n 5 script.sed
s/\<4\>\.\<([1-3][0-9]{0})\>/\1.4/g
s/\<3\>\.\<([1-2][0-9]{0})\>/\1.3/g
s/\<2\>\.\<([1-1][0-9]{0})\>/\1.2/g
s/\<1\>\.\<(0)\>/\1.1/g
ttop

उत्पन्न नियमित अभिव्यक्तियों के पीछे विचार उन संख्याओं के लिए मिलान पैटर्न है जो प्रत्येक पूर्णांक से कम हैं; उन दो नंबरों को आउट-ऑफ-ऑर्डर किया जाएगा, और इसलिए स्वैप किए गए हैं। नियमित अभिव्यक्तियों को कई OR विकल्पों में बांटा गया है। प्रत्येक आइटम से जुड़ी श्रेणियों पर ध्यान दें, कभी-कभी वे हैं {0}, जिसका अर्थ है कि तत्काल-पिछले आइटम को खोज से छोड़ा जाना है। रेगेक्स विकल्प, बाएं से दाएं की ओर, मिलान संख्या जो कि दी गई संख्या से छोटी है:

  • लोगों को जगह
  • दसवां स्थान
  • सैकड़ों जगह
  • (बड़ी संख्या के लिए आवश्यकतानुसार जारी रखा गया)
  • या परिमाण में छोटा होने से (अंकों की संख्या)

एक उदाहरण को समझने के लिए, 101(पठनीयता के लिए अतिरिक्त स्थान के साथ) लें:

s/ \<101\> \. \<(10[0-0][0-9]{0} | [0-9]{1,2})\> / \1.101 /g

यहां, पहला विकल्प 100 के माध्यम से 100 की संख्या की अनुमति देता है; दूसरा विकल्प 99 के माध्यम से 0 की अनुमति देता है।

एक और उदाहरण है 154:

s/ \<154\> \. \<(15[0-3][0-9]{0} | 1[0-4][0-9]{1} | [0-9]{1,2})\> / \1.154 /g

यहां पहला विकल्प 153 के माध्यम से 150 की अनुमति देता है; दूसरा 149 के माध्यम से 100 की अनुमति देता है, और अंतिम 99 के माध्यम से 0 की अनुमति देता है।

एक लूप में चार बार परीक्षण:

for test_run in {1..4}; do
    nums=$(( RANDOM%256 )).$(( RANDOM%256 )).$(( RANDOM%256 )).$(( RANDOM%256 ))
    printf 'nums=%s\n' "$nums"
    sed -E -f script.sed <<<"$nums"
done

आउटपुट:

nums=90.19.146.232
19.90.146.232
nums=8.226.70.154
8.70.154.226
nums=1.64.96.143
1.64.96.143
nums=67.6.203.56
6.56.67.203

-2

इनपुट को कई लाइनों में विभाजित करना

का उपयोग करके tr, आप एक अनियंत्रित सीमांकक का उपयोग करके इनपुट को कई लाइनों में विभाजित कर सकते हैं।

इस इनपुट को तब चलाया जा सकता है sort( -nयदि इनपुट संख्यात्मक है तो) का उपयोग करके ।

यदि आप आउटपुट में सीमांकक को बनाए रखना चाहते हैं, तो आप trफिर से सीमांकक को वापस जोड़ने के लिए उपयोग कर सकते हैं ।

उदाहरण के लिए एक सीमांकक के रूप में अंतरिक्ष का उपयोग करना

cat input.txt | tr " " "\n" | sort -n | tr "\n" " "

इनपुट: 1 2 4 1 4 32 18 3 आउटपुट:1 1 2 3 4 4 18 32


आप सुरक्षित रूप से संख्यात्मक आइटम मान सकते हैं, और हाँ: सीमांकक को प्रतिस्थापित किया जाना चाहिए।
जेफ स्कालर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.