বাশ: একটি আইপিভি 4 ঠিকানার চারটি বিভাগের একটি বের করুন


9

আমরা সিনট্যাক্স ব্যবহার করতে পারেন ${var##pattern}এবং ${var%%pattern}একটি IPv4 ঠিকানা শেষ ও প্রথম অধ্যায় বের করে আনতে:

IP=109.96.77.15
echo IP: $IP
echo 'Extract the first section using ${var%%pattern}: ' ${IP%%.*}
echo 'Extract the last section using ${var##pattern}: ' ${IP##*.}

প্যারামিটার সম্প্রসারণ ব্যবহার করে আমরা কীভাবে আইপিভি 4 ঠিকানার দ্বিতীয় বা তৃতীয় বিভাগটি বের করতে পারি?

আমার সমাধানটি এখানে: আমি একটি অ্যারে ব্যবহার করি এবং আইএফএস ভেরিয়েবলটি পরিবর্তন করি।

:~/bin$ IP=109.96.77.15
:~/bin$ IFS=. read -a ArrIP<<<"$IP"
:~/bin$ echo ${ArrIP[1]}
    96
:~/bin$ printf "%s\n" "${ArrIP[@]}"
    109
    96
    77
    15

এছাড়াও আমি কয়েকটি ব্যবহার সমাধানের লিখেছি awk, sedএবং cutকমান্ড।

এখন, আমার প্রশ্নটি হল: প্যারামিটার বিস্তারের উপর ভিত্তি করে এমন কোনও সহজ সমাধান রয়েছে যা অ্যারে এবং আইএফএস পরিবর্তন ব্যবহার করে না?


1
আপনি শুধুমাত্র সেট করা উচিত IFSজন্য readআছে:IFS=. read -a ArrIP<<<"$IP"
muru

1
কমপক্ষে একাধিক ভেরিয়েবল ব্যবহার না করে ব্যাশে নেই। একটি একক প্যারামিটার সম্প্রসারণ দ্বিতীয় বা তৃতীয় উপাদানগুলি পেতে পারে না। Zsh প্যারামিটারগুলি বিস্তারে বাসা বাঁধতে পারে, তাই এটি সম্ভবত সেখানেই সম্ভব।
মুরু

@ মুরু আপনি কি দয়া করে Zsh সমাধান সরবরাহ করতে পারেন?
বিজ্ঞ 9

4
আপনার কী গ্যারান্টি রয়েছে যে আপনি সর্বদা আইপি ভি 4 অ্যাড্রেস নিয়ে কাজ করবেন এবং কোনও আইপি ভি 6 অ্যাড্রেস পাবেন না?
মাওগ বলছেন মনিকা

4
কিছু কারণ IFS=. read a b c d <<< "$IP"গ্রহণযোগ্য নয় (আপনি যদি ব্যাশ ব্যবহার করেন তবে তা)? এটি কেন প্যারামিটার সম্প্রসারণ দিয়ে করতে হবে?
ইল্কচাচু

উত্তর:


16

আইএফএসের ডিফল্ট মান ধরে আপনি প্রতিটি অক্টেটের নিজস্ব ভেরিয়েবলের সাথে এটি বের করেন:

read A B C D <<<"${IP//./ }"

বা এর সাথে একটি অ্যারেতে:

A=(${IP//./ })

2
+1 টি। আমার কাছে মনে হচ্ছে এটি ওপিসের বিধিনিষেধ মেনে চলা সহজ, সরলতম পদ্ধতি।
ডিজিটাল ট্রমা

7

আপনার সমস্যার বিবৃতিটি আপনার ইচ্ছা থেকে কিছুটা উদার হতে পারে। একটি লুফোল শোষণের ঝুঁকিতে, এখানে মুরু সমাধানটির সমাধান দেওয়া হয়েছে :

first=${IP%%.*}
last3=${IP#*.}
second=${last3%%.*}
last2=${last3#*.}
third=${last2%.*}
fourth=${last2#*.}
echo "$IP -> $first, $second, $third, $fourth"

এটি কিছুটা আড়ষ্ট। এটি দুটি থ্রো-অ্যাওয়ে ভেরিয়েবলগুলি সংজ্ঞায়িত করে এবং আরও বিভাগগুলি হ্যান্ডেল করার জন্য এটি সহজেই খাপ খায় না (যেমন, কোনও ম্যাক বা আইপিভি 6 ঠিকানার জন্য)।  সের্গি কোলোডিয়াজনির উত্তর আমাকে উপরেরটিকে সাধারণীকরণে উদ্বুদ্ধ করেছিল:

slice="$IP"
count=1
while [ "$count" -le 4 ]
do
    declare sec"$count"="${slice%%.*}"
    slice="${slice#*.}"
    count=$((count+1))
done

এই সেট sec1, sec2, sec3এবং sec4, সঙ্গে যাচাই করা যেতে পারে যা

printf 'Section 1: %s\n' "$sec1"
printf 'Section 2: %s\n' "$sec2"
printf 'Section 3: %s\n' "$sec3"
printf 'Section 4: %s\n' "$sec4"
  • whileলুপ বুঝতে সহজ হবে না - এটি চারবার iterates।
  • Sergiy বেছে নেওয়া হয়েছে sliceএকটি পরিবর্তনশীল যে সঞ্চালিত জন্য নামের last3এবং last2(উপরে) আমার প্রথম দ্রবণে।
  • declare sec"$count"="value"নির্ধারিত একটি উপায় sec1, sec2, sec3এবং sec4 যখন countহয় 1, 2, 3এবং 4। এটি কিছুটা ভালো evalতবে নিরাপদ।
  • value, "${slice%%.*}", অনুরূপ আমার মূল উত্তর নির্ধারণ মান হয় first, secondএবং third

6

আমি বুঝতে পারি যে আপনি নির্দিষ্টভাবে এমন একটি সমাধান চেয়েছিলেন যা অস্থায়ীভাবে পুনরায় সংজ্ঞা দেয় না IFS, তবে আমার কাছে একটি মিষ্টি এবং সহজ সমাধান রয়েছে যা আপনি আবরণ করেন নি, তাই এখানে যান:

IFS=. ; set -- $IP

স্বল্প কমান্ড শেল এর আপনার IP ঠিকানা উপাদান করা হবে অবস্থানগত পরামিতি $1 , $2, $3, $4। তবে আপনি সম্ভবত প্রথমে মূলটি সংরক্ষণ করতে IFSএবং এরপরে পুনরুদ্ধার করতে চান।

কে জানে? সম্ভবত আপনি এই উত্তরটির সংক্ষিপ্ততা এবং দক্ষতার জন্য পুনর্বিবেচনা করবেন এবং গ্রহণ করবেন।

(এটি পূর্বে ভুল হিসাবে দেওয়া হয়েছিল IFS=. set -- $IP)


5
আমি মনে করি না যে এটি কাজ করে: আপনি যদি IFSএকই কমান্ড লাইনে পরিবর্তন করেন তবে একই কমান্ড লাইনের ভেরিয়েবলগুলি প্রসারিত করা হলে নতুন মান কার্যকর হয় না। সাথে একইx=1; x=2 echo $x
ইলক্কাছু

6
@ চ্যাপনার, তবে আবার setমোটেও ব্যবহার করে না $IFS, $IFSএটি কেবল বিভাজন শব্দের জন্য ব্যবহৃত হয় $IP, তবে এখানে এটি খুব দেরী করে দেওয়া হয়েছে, যাতে এর কোনও প্রভাব নেই। এই উত্তরটি মূলত ভুল। IP=109.96.77.15 bash -c 'IFS=. set -- $IP; echo "$2"'পসিক্স মোডে থাকুক বা না থাকুক কিছুই আউটপুট করে না। আপনার প্রয়োজন হবে IFS=. command eval 'set -- $IP', বাIFS=. read a b c d << "$IP"
স্টাফেন চেজেলাস

4
এটি সম্ভবত আপনার পক্ষে কাজ করে কারণ আপনি .আপনার আগের পরীক্ষার একটিতে আইএফএস স্থাপন করেছিলেন set চালান IP=1.2.3.4 bash -xc 'IFS=. set $IP; echo "$2"'এবং আপনি দেখতে পাবেন যে এটি কাজ করে না। এবং IP=1.2.3.4 bash -o posix -xc 'IFS=. set $IP; echo "\$1=$1 \$2=$2 IFS=$IFS"'@ চিপনার পয়েন্টটি বর্ণনা করার জন্য দেখুন।
স্টাফেন চেজেলাস

2
তাড়াহুড়ো নষ্ট করে দিয়েছে, উত্তরটি আপাতদৃষ্টিতে ভুল, এবং কাজটিতে সংশোধন করা উচিত, যেহেতু এটি এখনও প্রায় কোড সহ আমি কীভাবে করব তা মোটামুটি।
টিকটিকি 21

3
@ ব্যবহারকারী1404316, আপনি এটি পরীক্ষা করার জন্য ব্যবহৃত আদেশগুলির সঠিক সেটটি পোস্ট করতে পারেন? (সম্ভবত আপনার শেলের সংস্করণ, সম্ভবত।) এখানে আরও চার জন ব্যবহারকারী আছেন যারা আপনাকে এখানে মন্তব্যগুলিতে বলেছিলেন যে এটি উত্তরে লেখা হিসাবে কাজ করে না। উদাহরণ সহ।
ইল্কাচ্চু

5

সবচেয়ে সহজ নয় , তবে আপনি এর মতো কিছু করতে পারেন:

$ IP=109.96.77.15
$ echo "$((${-+"(${IP//./"+256*("}))))"}&255))"
109
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>8&255))"
96
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>16&255))"
77
$ echo "$((${-+"(${IP//./"+256*("}))))"}>>24&255))"
15

যে ksh93 কাজ করা উচিত (যেখানে যে ${var//pattern/replacement}অপারেটর থেকে আসে), bash4.3+,, busybox sh, yash, mkshএবং zsh, যদিও অবশ্যই মধ্যে zsh, সেখানে অনেক সহজ পন্থা আছে । এর পুরানো সংস্করণগুলিতে bashআপনাকে অভ্যন্তরীণ উদ্ধৃতিগুলি সরিয়ে ফেলতে হবে। এটি বেশিরভাগ অন্যান্য শেলগুলিতে মুছে ফেলা সেই অভ্যন্তরীণ উদ্ধৃতিগুলির সাথে কাজ করে তবে ksh93 নয়।

এটি ধরে নেওয়া হয়েছে যে $IPএকটি আইপিভি 4 ঠিকানার বৈধ কোয়াড-দশমিক উপস্থাপনা রয়েছে (যদিও এটি কোয়াড-হেক্সাডেসিমাল উপস্থাপনার জন্যও কাজ করবে 0x6d.0x60.0x4d.0xf(এবং কিছু শেলের মধ্যে অষ্টালও তবে দশমিকের মধ্যে মানগুলি আউটপুট করবে))। যদি বিষয়বস্তু $IPকোনও অবিশ্বস্ত উত্স থেকে আসে তবে তা কমান্ড ইঞ্জেকশন দুর্বলতার পরিমাণ।

মূলত, আমরা প্রতিটির সাথে প্রতিস্থাপন .করার $IPসাথে সাথে +256*(আমরা মূল্যায়নটি শেষ করি:

 $(( (109+256*(96+256*(77+256*(15))))>> x &255 ))

সুতরাং আমরা IPv4 ঠিকানার মতো those বাইটের মধ্যে একটি 32 বিট পূর্ণসংখ্যার অবশেষে তৈরি করছি (যদিও বাইটগুলি বিপরীত করা হয়েছে) then এবং তারপরে >>, &প্রবাহিত অপারেটরগুলি ব্যবহার করে প্রাসঙ্গিক বাইটগুলি বের করতে পারেন।

আমরা ${param+value}স্ট্যান্ডার্ড অপারেটরটি ব্যবহার করি (এখানে $-যা সর্বদা সেট করার নিশ্চয়তা দেওয়া আছে) ঠিক এর পরিবর্তে valueঅন্যথায় পাটিগণিত বিশিষ্ট পার্থক্যের সাথে মিল নেই complain এখানে শেলটি ))খোলার জন্য সমাপনীটি খুঁজে পেতে পারে $((এবং তারপরে অভ্যন্তরীণ প্রসারগুলি সম্পাদন করতে পারে যার ফলশ্রুতিতে পাটিগণিতের প্রকাশ ঘটে।

সঙ্গে $(((${IP//./"+256*("}))))&255))পরিবর্তে, শেল দ্বিতীয় ও তৃতীয় আচরণ করবেন )ক্লোজিং সেখানে গুলি ))জন্য $((এবং একটি বাক্য গঠন ত্রুটি প্রতিবেদন করুন।

Ksh93 এ, আপনি এটি করতে পারেন:

$ echo "${IP/@(*).@(*).@(*).@(*)/\2}"
96

bash, mksh, zsh Ksh93 এর অনুলিপি করেছেন ${var/pattern/replacement}অপারেটর কিন্তু যে না ক্যাপচার-গ্রুপ অংশ হ্যান্ডলিং। zshএটি একটি ভিন্ন বাক্য গঠন সহ সমর্থন করে:

$ setopt extendedglob # for (#b)
$ echo ${IP/(#b)(*).(*).(*).(*)/$match[2]}'
96

bashএর রিজেক্সএক্স ম্যাচিং অপারেটরে ক্যাপচার গ্রুপ হ্যান্ডলিংয়ের কিছু ফর্ম সমর্থন করে , কিন্তু এতে নেই ${var/pattern/replacement}

প্যাসিকলি, আপনি ব্যবহার করতে চাই:

(IFS=.; set -o noglob; set -- $IP; printf '%s\n' "$2")

noglobমান জন্য খারাপ চমকের এড়াতে $IPমত 10.*.*.*subshell, বিকল্প এবং যারা পরিবর্তন করার সুযোগ সীমিত করতে $IFS


¹ একটি আইপিভি 4 ঠিকানা কেবল একটি 32 বিট পূর্ণসংখ্যা এবং 127.0.0.1 উদাহরণস্বরূপ অনেকের মধ্যে একটি (যদিও সর্বাধিক সাধারণ) পাঠ্য উপস্থাপনা। লুপব্যাক ইন্টারফেসের একই সাধারণ আইপিভি 4 ঠিকানাটি 0x7f000001 বা 127.1 হিসাবে প্রতিনিধিত্ব করা যেতে পারে (এটি সম্ভবত 1127.0 / 8 ক্লাস এ নেটওয়ার্কের ঠিকানা হিসাবে বলা যেতে পারে ), বা 0177.0.1, বা 1 এর অন্যান্য সংমিশ্রণগুলি অষ্টাল, দশমিক বা হেক্সাডেসিমাল হিসাবে প্রকাশিত 4 টি সংখ্যা। pingউদাহরণস্বরূপ আপনি এই সমস্তগুলিতে পাস করতে পারেন এবং আপনি দেখতে পাবেন যে তারা সমস্ত লোকালহোস্টে পিং করবে।

যদি আপনি সালিসি অস্থায়ী পরিবর্তনশীল (এখানে $n) সেট করার পার্শ্ব প্রতিক্রিয়াটিকে কিছু মনে করেন না , bashবা ksh93বা zsh -o octalzeroesবা lksh -o posix, আপনি কেবলমাত্র এই সমস্ত উপস্থাপনাগুলি 32 বিট পূর্ণসংখ্যার সাথে ফিরে রূপান্তর করতে পারেন:

$((n=32,(${IP//./"<<(n-=8))+("})))

এবং তারপরে উপরের মতো >>/ &সংমিশ্রণ সহ সমস্ত উপাদানগুলি বের করুন ।

$ IP=0x7f000001
$ echo "$((n=32,(${IP//./"<<(n-=8))+("})))"
2130706433
$ IP=127.1
$ echo "$((n=32,(${IP//./"<<(n-=8))+("})))"
2130706433
$ echo "$((n=32,((${IP//./"<<(n-=8))+("}))>>24&255))"
127
$ perl -MSocket -le 'print unpack("L>", inet_aton("127.0.0.1"))'
2130706433

mkshপাটিগণিতের বহিঃপ্রকাশের জন্য স্বাক্ষরিত 32 বিট ইন্টিজার ব্যবহার করে, আপনি $((# n=32,...))স্বাক্ষরবিহীন 32 বিট সংখ্যার (এবং এর posixজন্য অক্টাল ধ্রুবকগুলি সনাক্ত করার বিকল্প) ব্যবহার করতে বাধ্য করতে পারেন ।


আমি বড় ধারণাটি বুঝতে পারি, তবে এর ${-+আগে কখনও দেখিনি । আমি এটিতে কোনও নথিও পাই না। এটি কাজ করে, তবে আমি নিশ্চিত করতে আগ্রহী, এটি কি কেবল স্ট্রিংটিকে গাণিতিক প্রকাশে পরিণত করা? আমি কোথায় আনুষ্ঠানিক সংজ্ঞা পেতে পারি? এছাড়াও, প্যারামিটার এক্সপেনশন রিপ্লেসমেন্ট বিভাগের অতিরিক্ত কোটেশনগুলি জিএনইউ ব্যাশ, সংস্করণ 4.1.2 (2) -রিলিজ সেন্টোস 6.6 এ কাজ করে না। পরিবর্তে আমাকে এটি করতে হয়েছিলecho "$((${-+"(${IP//./+256*(}))))"}>>16&255))"
লেভি উজোডাইক

1
@ লেভিউউজাইক, সম্পাদনা দেখুন।
স্টাফেন চেজেলাস

4

Zsh এর সাহায্যে আপনি প্যারামিটার বিকল্পগুলি বাসাতে পারেন:

$ ip=12.34.56.78
$ echo ${${ip%.*}##*.}
56
$ echo ${${ip#*.}%%.*}
34

বাশে এটি সম্ভব নয়।


1
ইন zsh, আপনি পছন্দ করতে পারেন${${(s(.))ip}[3]}
স্টাফেন চ্যাজেলাস

4

অবশ্যই, আসুন হাতির খেলা খেলি।

$ ipsplit() { local IFS=.; ip=(.$*); }
$ ipsplit 10.1.2.3
$ echo ${ip[1]}
10

অথবা

$ ipsplit() { local IFS=.; echo $*; }
$ set -- `ipsplit 10.1.2.3`
$ echo $1
10

2
"হাতির খেলা" কী?
ওয়াইল্ডকার্ড

1
@ উইল্ডকার্ড ধরণের একটি উপবৃত্তাকার শ্লেষ / রসিকতা, এটি উভয় অন্ধ-জনগণ-একটি হাতির গল্প বর্ণনা করার জন্য একটি রেফারেন্স, সেখানে প্রত্যেকের নিজস্ব গ্রহণ করা এবং রাজার প্রাচীন রীতিনীতি যা দেখতে চেয়েছিল তার দিকে কিছু অংশ থাকতে পারে ধ্বংসাত্মক ব্যয়বহুল রক্ষণাবেক্ষণের সাথে উপহার দেওয়ার জন্য, শতাব্দীর পরিক্রমায় বিনোদনমূলক মূল্যকে পুনরায় ফিরিয়ে আনার ঝুঁকিপূর্ণ উপহারগুলিকে উপহার দিয়েছিলেন Both দু'জনেই এখানে আবেদন করেছেন বলে মনে হয়েছে :-)
জেথিল

3

সঙ্গে IP=12.34.56.78

IFS=. read a b c d <<<"$IP"

এবং

#!/bin/bash
IP=$1

regex="(${IP//\./)\.(})"
[[ $IP =~ $regex ]]
echo "${BASH_REMATCH[@]:1}"

বর্ণনা:

${IP// }আইপি-র প্রতিটি বিন্দুটিকে একটি খোলার বন্ধনীতে একটি বিন্দু এবং বন্ধকৃত প্রথম বন্ধনে রূপান্তর করতে প্যারামিটার বিস্তারের ব্যবহার of একটি প্রাথমিক বন্ধনী এবং একটি বন্ধনী প্রথম বন্ধন যুক্ত করা, আমরা পাই:

regex=(12)\.(34)\.(56)\.(78)

যা পরীক্ষার বাক্য গঠনে রেজেক্স ম্যাচের জন্য চারটি ক্যাপচার প্যারেনেসিস তৈরি করবে:

[[ $IP =~ $regex ]]

এটি প্রথম উপাদান ছাড়াই অ্যারে BASH_REMATCH মুদ্রণের অনুমতি দেয় (পুরো রেজেক্স ম্যাচ):

echo "${BASH_REMATCH[@]:1}"

প্যারেনথেসিসের পরিমাণটি স্বয়ংক্রিয়ভাবে মিলে যাওয়া স্ট্রিংয়ের সাথে সামঞ্জস্য হয়। সুতরাং, এটি পৃথক দৈর্ঘ্যের হওয়া সত্ত্বেও কোনও আইপিভি 6 ঠিকানার একটি ম্যাক বা একটি EUI-64 এর সাথে মিলবে:

#!/bin/bash
IP=$1

regex="(${IP//:/):(})"
[[ $IP =~ $regex ]]
echo "${BASH_REMATCH[@]:1}"

এটি ব্যবহার করছি:

$ ./script 00:0C:29:0C:47:D5
00 0C 29 0C 47 D5

$ ./script 00:0C:29:FF:FE:0C:47:D5
00 0C 29 FF FE 0C 47 D5

3

এখানে পসিক্সের সাথে একটি ছোট সমাধান করা হয়েছে /bin/sh(আমার ক্ষেত্রে এটি dash), এমন একটি ফাংশন যা বারবার প্যারামিটার এক্সপেনশন ব্যবহার করে (তাই IFSএখানে নেই), এবং নাম পাইপ noglobএবং স্টিফেনের উত্তরে উল্লিখিত কারণগুলির জন্য বিকল্প অন্তর্ভুক্ত করে ।

#!/bin/sh
set -o noglob
get_ip_sections(){
    slice="$1"
    count=0
    while [ -n "${slice}" ] && [ "$count" -ne 4 ]
    do
        num="${slice%%.*}"
        printf '%s ' "${num}"
        slice="${slice#*${num}.}"
        count=$((count+1))
    done
}

ip="109.96.77.15"
named_pipe="/tmp/ip_stuff.fifo"
mkfifo "${named_pipe}"
get_ip_sections "$ip" > "${named_pipe}" &
read sec1 sec2 sec3 sec4 < "${named_pipe}"
printf 'Actual ip:%s\n' "${ip}"
printf 'Section 1:%s\n' "${sec1}"
printf 'Section 3:%s\n' "${sec3}"
rm  "${named_pipe}"

এটি তাই হিসাবে কাজ করে:

$ ./get_ip_sections.sh 
Actual ip:109.96.77.15
Section 1:109
Section 3:77

এবং সাথে ipপরিবর্তিত হয়েছে109.*.*.*

$ ./get_ip_sections.sh 
Actual ip:109.*.*.*
Section 1:109
Section 3:*

4 পুনরাবৃত্তির লুপ কিপিং কাউন্টারে বৈধ IPv4 ঠিকানার 4 টি বিভাগ রয়েছে, যখন নামক পাইপযুক্ত অ্যাক্রোব্যাটিকস লুপের সাবশেলে আটকে থাকা ভেরিয়েবলের বিপরীতে স্ক্রিপ্টের মধ্যে আইপি ঠিকানার অংশগুলি আরও ব্যবহার করার প্রয়োজন পড়ে।


আমি আপনার উত্তরটি পরিবর্তন করেছি যাতে এটি কোনও পাইপ ব্যবহার না করে এবং এটি আমার বিদ্যমান উত্তরে যুক্ত করে
জি-ম্যান বলছেন 'পুনরায় ইনস্টল করুন মনিকা'


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.