আমি কীভাবে সংখ্যায়িতভাবে সীমানাঙ্কিত আইটেমগুলির একক লাইনকে বাছাই করতে পারি?


11

আমার সংখ্যার একটি লাইন (বা অনেকগুলি লাইন) রয়েছে যা একটি স্বেচ্ছাসেবী চরিত্র দ্বারা সীমিত করা হয়। প্রতিটি লাইনের আইটেমগুলিকে সংখ্যায় বাছাই করতে, ডিলিমিটারটি ধরে রেখে আমি কোন ইউনিক্স সরঞ্জামগুলি ব্যবহার করতে পারি?

উদাহরণ অন্তর্ভুক্ত:

  • সংখ্যার তালিকা; ইনপুট: 10 50 23 42; সাজানো:10 23 42 50
  • আইপি ঠিকানা; ইনপুট: 10.1.200.42; সাজানো:1.10.42.200
  • যে CSV; ইনপুট: 1,100,330,42; সাজানো:1,42,100,330
  • নল-সীমা নির্দেশ করা; ইনপুট: 400|500|404; সাজানো:400|404|500

যেহেতু ডিলিমিটারটি স্বেচ্ছাচারী তাই আপনার পছন্দের একটি একক-অক্ষর ডিলিমিটার ব্যবহার করে একটি উত্তর সরবরাহ করতে (বা প্রসারিত) নির্দ্বিধায় অনুভব করুন।


8
আপনার এটি কোডগল্ফে পোস্ট করা উচিত :)
ivanivan

1
এখানেও একই ধরণের প্রশ্ন রয়েছে আমি কি এর লিঙ্কটি যুক্ত করতে চাই বাছাই করে ফাইলের নামগুলিতে শব্দগুলি বর্ণিত করতে?
нιηসнιη

কেবলমাত্র একটি ইঙ্গিত যা cutতার -dবিকল্পের সাথে স্বেচ্ছাসেবী সীমানাকে সমর্থন করে ।
ওলেগ লোবাচেভ

ডিএসভি'র এই চারটি উদাহরণ একই ফাইলে রয়েছে কিনা বা চারটি ভিন্ন ফাইলের নমুনা কিনা তা দয়া করে পরিষ্কার করুন ।
এগ্রি

2
অন্যান্য কয়েকটি মন্তব্য দেখে: ডিলিমিটারটি নির্বিচারে হয় তবে ইনপুটটিতে ধারাবাহিকভাবে ব্যবহৃত হবে। ডেটা প্রযোজকের পক্ষ থেকে বুদ্ধি অনুমান করুন যে তারা সীমানা হিসাবে এবং ডেটাতে কমা ব্যবহার করবে না (উদাহরণস্বরূপ, 4,325 comma 55 comma 42,430ঘটবে না এবং হবে না 1.5 period 4.2)।
জেফ স্ক্যালার হলেন

উত্তর:


12

আপনি এটি দিয়ে এটি অর্জন করতে পারেন:

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

আপনার ডিলিমিটারের সাথে বিন্দুগুলি প্রতিস্থাপন .করুন।
যোগ -uকরার জন্য sortকমান্ড উপরে সদৃশ মুছে ফেলার জন্য।


বা gawk( জিএনইউ 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)

যেমন একটি ,

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। এটি মুদ্রণের পরেও নতুন লাইনটি যুক্ত করে। বিভক্ত অংশের জন্যও -a(সহ -F) দেখুন ।
স্টাফেন চেজেলাস

1
সঙ্গে -lএবং -F: এটা এমনকি nicer এরperl -F'/\./' -le 'print join(".", sort {$a <=> $b} @F)'
muru

@ স্টাফেন চ্যাজেলাস -lবিকল্পটির জন্য ধন্যবাদ ; আমি মিস করতাম!
স্টিফেন হ্যারিস

1
@ মুরু আমি -Fপতাকাটি মূলত ব্যবহার করিনি কারণ এটি সমস্ত সংস্করণে সঠিকভাবে কাজ করে না (যেমন, সেন্টোস - - পার্ল ৫.১6.৩ এ আপনার লাইন - ফাঁকা আউটপুট দেয়, যদিও এটি ডিবিয়ান 9 এ সূক্ষ্মভাবে কাজ করে)। তবে এর সাথে মিলিত -pকিছুটা ছোট ফলাফল দেয়, তাই আমি যুক্ত করেছি যে এটির উত্তর হিসাবে। কীভাবে -Fব্যবহার করা যায় তা দেখাচ্ছে । ধন্যবাদ!
স্টিফেন হ্যারিস

2
@StephenHarris যে কারণ Perl এর নতুন সংস্করণে স্বয়ংক্রিয়ভাবে যোগ করা -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

দু: খজনকভাবে I / O ম্যানুয়ালি করার কারণে পার্ল সংস্করণটির তুলনায় এটি অনেক কম মার্জিত হয়।


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'

এটি <<<কেবলমাত্র ব্যবহারের কারণে বাশ দরকার । যদি এটি এখানে-ডক দিয়ে প্রতিস্থাপন করা হয় তবে সমাধানটি পিক্সির জন্য বৈধ।
এই ট্যাব, স্পেস বা শেল উল্লিখিত glob অক্ষর ক্ষেত্র বাছাই করতে সক্ষম হয় ( *, ?, [)। নতুন লাইন নয় কারণ প্রতিটি লাইন বাছাই করা হচ্ছে।

ফাইলের নামগুলি প্রক্রিয়া <<<"$2"করতে পরিবর্তন করুন <"$2"এবং এটিকে কল করুন:

shsort '.'    infile

ডিলিমিটার পুরো ফাইলের জন্য একই। যদি এটি সীমাবদ্ধতা হয় তবে এটি উন্নত হতে পারে।

তবে মাত্র 6000 লাইন সহ একটি ফাইল প্রক্রিয়া করতে 15 সেকেন্ড সময় নেয়। সত্যিই, ফাইলগুলি প্রক্রিয়া করার জন্য শেলটি সেরা সরঞ্জাম নয়।

awk

কয়েকটি লাইনের বেশি (কয়েক দশকের বেশি) এর জন্য একটি আসল প্রোগ্রামিং ভাষা ব্যবহার করা ভাল। একটি বিশুদ্ধ সমাধান হতে পারে:

#!/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

sedআইপি ঠিকানার অক্টেটগুলি বাছাই করতে ব্যবহার করে

sedএকটি অন্তর্নির্মিত sortফাংশন নেই, তবে যদি আপনার ডেটা পর্যাপ্ত পরিসীমাতে সীমিত থাকে (যেমন আইপি অ্যাড্রেস সহ), আপনি একটি সেড স্ক্রিপ্ট তৈরি করতে পারেন যা ম্যানুয়ালি একটি সাধারণ বুদ্বুদ সাজানোর প্রয়োগ করে । মৌলিক প্রক্রিয়াটি হ'ল সংক্রমণের বাইরে থাকা সংখ্যার সন্ধান করা- যদি সংখ্যাগুলি ক্রমবর্ধমান হয় তবে এগুলি স্যুপ করুন।

sedঅক্টেট প্রথম দুই জোড়া জন্য এক (ক trailing বিভেদক অত্যাচার তৃতীয় অক্টেট শেষে চিহ্নিত করতে উপস্থিত হতে), এবং A: স্ক্রিপ্ট নিজেই আউট-অফ-অর্ডার সংখ্যার প্রতিটি জোড়া জন্য দুটি অনুসন্ধান-এবং-swap 'র কমান্ড ধারণ করে তৃতীয় জোড় আষ্টেটের জন্য দ্বিতীয় (ইওল দিয়ে শেষ)। যদি অদলবদল ঘটে থাকে তবে প্রোগ্রামটি স্ক্রিপ্টের শীর্ষে শাখাগুলি খুঁজে বের করবে না numbers অন্যথায়, এটি প্রস্থান করে।

উত্পন্ন স্ক্রিপ্টটি কিছু অংশে রয়েছে:

$ 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

উৎপাদিত স্ক্রিপ্ট নিম্নলিখিত প্রকরণ শব্দ সীমানা চিহ্নিতকারী ব্যবহার \<এবং \>দ্বিতীয় প্রতিকল্পন প্রয়োজন পরিত্রাণ পেতে। এটি sedনিজে তৈরির সময়কে হ্রাস করার পাশাপাশি উত্পাদিত স্ক্রিপ্টটির আকার 1.3 মেগাবাইট থেকে 900 কেবি পর্যন্ত কমিয়ে দেয় ( sedবাস্তবায়নের কী ব্যবহার হচ্ছে তার উপর নির্ভর করে মূলের প্রায় 50% -75% ):

#!/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করা হাস্যকর, এ কারণেই এটি একটি আকর্ষণীয় চ্যালেঞ্জ।
কুসালানন্দ

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ত্রুটি ফেরায়)।


এটি এটিকে অনুপ্রাণিত করে ।
এজিসি

2

এই উত্তরটি কিউ সম্পর্কে ভুল বোঝাবুঝির ভিত্তিতে তৈরি হয়েছে তবে কিছু ক্ষেত্রে এটি যাইহোক সঠিক হতে পারে happens যদি ইনপুটটি সম্পূর্ণ প্রাকৃতিক সংখ্যা হয় এবং প্রতি-লাইনটিতে কেবল একটি ডেলিফিমিটার থাকে (যেমন Q. তে থাকা নমুনা ডেটা রয়েছে), এটি সঠিকভাবে কাজ করে। এটি লাইনের সাথে ফাইলগুলিও হ্যান্ডেল করবে যেগুলির প্রত্যেকের নিজস্ব ডিলিমিটার রয়েছে, যা যা চেয়েছিল তার চেয়ে কিছুটা বেশি।

এই শেল ফাংশনটি readস্ট্যান্ডার্ড ইনপুট থেকে, প্রতিটি লাইনে নির্দিষ্ট ডিলিমিটার সন্ধান করতে (সঞ্চিত ) পসিক্স প্যারামিটার প্রতিস্থাপন$d ব্যবহার trকরে এবং $dএকটি লাইন \nএবং sortসেই লাইনটির ডেটার সাথে প্রতিস্থাপন করতে ব্যবহার করে, তারপরে প্রতিটি লাইনের মূল সীমানা পুনরুদ্ধার করে:

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 কেবি বড় হবে। 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

উত্পন্ন নিয়মিত প্রকাশের পেছনের ধারণাটি প্রতিটি সংখ্যার চেয়ে কম সংখ্যার জন্য প্যাটার্ন ম্যাচের জন্য; এই দুটি সংখ্যা অ-অফ-অর্ডার হবে এবং তাই অদলবদল করা হবে। নিয়মিত প্রকাশগুলি বেশ কয়েকটি ওআর বিকল্পগুলিতে বিভক্ত হয়। প্রতিটি আইটেমের সাথে যুক্ত রেঞ্জগুলিকে ঘনিষ্ঠ মনোযোগ দিন, কখনও কখনও সেগুলি হয় {0}অর্থাত্ তাত্ক্ষণিক-পূর্ববর্তী আইটেমটি অনুসন্ধান থেকে বাদ দেওয়া উচিত। বাম-থেকে-ডান, মিলের সংখ্যাগুলি যা প্রদত্ত সংখ্যার চেয়ে ছোট ছোটগুলি দ্বারা রেজেক্স বিকল্পগুলি:

  • বেশী জায়গা
  • দশকের জায়গা
  • শত জায়গা
  • (প্রয়োজন হিসাবে চালিয়ে যাও, বৃহত সংখ্যার জন্য)
  • বা আকারে ছোট হয়ে (অঙ্কের সংখ্যা)

একটি উদাহরণ বানান করতে, নিন 101(পাঠযোগ্যতার জন্য অতিরিক্ত স্থান সহ):

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

এখানে, প্রথম বিকল্পটি 100 এর মাধ্যমে 100 নম্বরগুলিকে অনুমতি দেয়; দ্বিতীয় বিকল্প 0 থেকে 99 এর মধ্যে অনুমতি দেয়।

আরেকটি উদাহরণ হ'ল 154:

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

এখানে প্রথম বিকল্পটি 150 এর মাধ্যমে 153 এর অনুমতি দেয়; দ্বিতীয়টি 149 এর মাধ্যমে 100 কে এবং শেষটি 0 থেকে 99 এর মধ্যে অনুমতি দেয়।

একটি লুপে চারবার পরীক্ষা করা:

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


আপনি নিরাপদে সংখ্যাসূচক আইটেম ধরে নিতে পারেন, এবং হ্যাঁ: ডিলিমিটারটি প্রতিস্থাপন করা উচিত।
জেফ শ্যাচলার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.