/ বিন / এস-এ কোলন-এ স্প্লিট স্ট্রিং


9

আমার dashস্ক্রিপ্টটি আকারে একটি প্যারামিটার নেয় hostname:port, অর্থাত:

myhost:1234

বন্দরটি alচ্ছিক, যেমন:

myhost

আমাকে হোস্ট এবং পোর্টটি পৃথক ভেরিয়েবলের মধ্যে পড়তে হবে। প্রথম ক্ষেত্রে, আমি এটি করতে পারি:

HOST=${1%%:*}
PORT=${1##*:}

তবে এটি দ্বিতীয় ক্ষেত্রে কার্যকর হয় না, যখন বন্দর বাদ দেওয়া হয়েছিল; echo ${1##*:}খালি স্ট্রিংয়ের পরিবর্তে কেবল হোস্টনামটি দেয়।

বাশে, আমি এটি করতে পারি:

IFS=: read A B <<< asdf:111

তবে তাতে কাজ হয় না dash

আমি স্ট্রিং বিভক্ত করতে পারেন :ড্যাশ মধ্যে, বাহ্যিক প্রোগ্রাম (invoking ছাড়া awk, trইত্যাদি)?


4
আপনি যদি আইপিভি 6 সমর্থন করতে চান তবে শেষ কোলনে বিভক্ত হওয়ার বিষয়টি নিশ্চিত করুন, এবং বর্গাকার বন্ধনীগুলির ভিতরে
কলোনগুলিতে

@ ফেরিবিগ %%এটিকে লোভী করেছে (বিপরীতে %), তাই এটি আসলে এটি করে, অন্তত কিছুটা অংশে; এটি সঙ্গে কাজ করবে না ##
jpaugh

উত্তর:


18

শুধু কর:

case $1 in
  (*:*) host=${1%:*} port=${1##*:};;
  (*)   host=$1      port=$default_port;;
esac

আপনি পরিবর্তন করতে পারেন case $1থেকে case ${1##*[]]}এর মানের জন্য অ্যাকাউন্টে $1মত [::1](ছাড়া একটি IPv6 ঠিকানা বন্দর অংশ)।

বিভক্ত করতে, আপনি স্প্লিট + গ্লোব অপারেটরটি ব্যবহার করতে পারেন (প্যারামিটারের সম্প্রসারণকে অব্যক্ত রেখে দিন) এটি সর্বোপরি যা হ'ল:

set -o noglob # disable glob part
IFS=:         # split on colon
set -- $1     # split+glob

host=$1 port=${2:-$default_port}

(যদিও এটি হোস্টনামগুলিতে মঞ্জুরি দেয় না যাতে কোনও কোলন থাকে (উপরের আইপিভি 6 ঠিকানার মতো))।

এই বিভক্ত + গ্লোব অপারেটরটি এই পথে চলে যায় এবং বাকি সময়গুলিকে এত বেশি ক্ষতি করে যে এটিকে কেবল ন্যায্য বলে মনে হয় যখনই এটি প্রয়োজন হবে তখনই ব্যবহার করা হবে (যদিও, আমি সম্মত হব যে এটি পজিক্সের shকোনও নেই বলে বিবেচনা করা খুব জটিল c স্থানীয় সুযোগ জন্য সমর্থন ভেরিয়েবল (জন্য তন্ন তন্ন $IFSএখানে) কিংবা অপশন (জন্য noglobএখানে) (যদিও ashও ডেরিভেটিভস পছন্দ dashবেশী যে (না একসঙ্গে যেমন AT & T এর বাস্তবায়নের সঙ্গে কিছু ksh, zshএবং bash4.4 এবং উপরোক্ত))।

নোটটির IFS=: read A B <<< "$1"নিজস্ব কয়েকটি সমস্যা রয়েছে:

  • আপনি ভুলে গেছেন -rযার অর্থ ব্যাকস্ল্যাশ কিছু বিশেষ প্রক্রিয়াজাতকরণের মধ্য দিয়ে যাবে।
  • এটা বিভক্ত হবে [::1]:443মধ্যে [এবং :1]:443পরিবর্তে [এবং খালি স্ট্রিং (যার জন্য আপনি প্রয়োজন চাই IFS=: read -r A B rest_ignoredবা [::1]এবং 443(যার জন্য আপনি যে পদ্ধতির ব্যবহার করতে পারবেন না)
  • এটি একটি নতুন লাইন চরিত্রের প্রথম উপস্থিতির অতীত সমস্ত কিছু ছড়িয়ে দেয়, সুতরাং এটি নির্বিচারে স্ট্রিং ব্যবহার করা যাবে না (যদি না আপনি ব্যবহার -d ''করেন zshবা bashডেটাতে NUL অক্ষর না থাকে তবে তবে নোট করুন যে হিস্ট্রস্ট্রিংস (বা হেরডোকস) একটি যুক্ত করে না অতিরিক্ত নিউলাইন চরিত্র!)
  • ইন zsh(যেখানে সিনট্যাক্সটি এসেছে) এবং bashএখানে স্ট্রিংগুলি অস্থায়ী ফাইল ব্যবহার করে প্রয়োগ করা হয়, সুতরাং এটি ${x#y}+ গ্লোব অপারেটরগুলি ব্যবহার বা বিভক্ত করার চেয়ে সাধারণত কম দক্ষ ।

7
2018 সালে, নতুন বছরের রেজোলিউশন হিসাবে, আমাদের সকলের স্ক্রিপ্টগুলি লেখা বন্ধ করা উচিত যা আইপিভি 6 এর সাথে ভেঙে যায়।
ফিলিপস

@ ফিলিপোস দুই সপ্তাহের মধ্যে দেরী!
রোন

@ রন জন: দু'দশক দেরী হয়ে গেছে, একরকম।
ফিলিপস

6

কেবল :একটি পৃথক বিবৃতিতে অপসারণ ; এছাড়াও, পোর্টটি পেতে input হোস্টটিকে ইনপুট থেকে সরান:

host=${1%:*}
port=${1#"$host"}
port=${port#:}


1

একটি এখানে স্ট্রিং এখানে একটি একক লাইন ডকুমেন্টের জন্য একটি সিনট্যাক্টিক শর্টকাট।

$ set myhost:1234
$ IFS=: read A B <<EOF
> $1
> EOF
$ echo "$A"
myhost
$ echo "B"
1234
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.