এই প্রশ্নের উত্তরগুলির সবগুলিই কোনও না কোনওভাবে ভুল।
ভুল উত্তর # 1
IFS=', ' read -r -a array <<< "$string"
1: এটি একটি অপব্যবহার $IFS
। মান $IFS
পরিবর্তনশীল হয় না একটি হিসাবে গ্রহণ একক পরিবর্তনশীল দৈর্ঘ্যের , স্ট্রিং বিভাজক বরং এটি একটি হিসাবে নেওয়া হয় সেট এর একক-অক্ষর স্ট্রিং বিভাজক, যেখানে প্রতিটি ক্ষেত্রের যে read
ইনপুট লাইন থেকে বন্ধ splits দ্বারা সমাপ্ত করা যেতে পারে কোনো সেট চরিত্র ( এই উদাহরণে কমা বা স্থান)।
প্রকৃতপক্ষে, প্রকৃত স্টিকারদের জন্য সেখানে, পুরো অর্থটি $IFS
কিছুটা বেশি জড়িত। থেকে ব্যাশ ম্যানুয়াল :
শেল একইরূপে এর প্রতিটি অক্ষর IFS একটি বিভেদক, এবং ক্ষেত্র terminators এই অক্ষর ব্যবহার করে শব্দের মধ্যে টুকরা অন্যান্য প্রসারণও এর ফলাফল নেই। যদি আইএফএসটি সেট না করা থাকে, বা এর মানটি হ'ল <space><tab> <নিউলাইন> , ডিফল্ট, তারপরে পূর্ববর্তী বিস্তারের ফলাফলের শুরু এবং শেষে <স্পেস> , <ট্যাব> এবং <নিউলাইন> এর ক্রমগুলি উপেক্ষা করা হয় এবং আইএফএস অক্ষরের কোনও অনুক্রম শুরুর বা শেষের দিকে নয়, শব্দগুলি সীমিত করে দেয়। যদি IFS ডিফল্ট ছাড়া অন্য কোনো মূল্য আছে, তারপর হোয়াইটস্পেস অক্ষরের ক্রমের সাথে <স্পেস> , <ট্যাব> এবং <শব্দের শুরুতে ও শেষে উপেক্ষা করা হয়, যতক্ষণ না হোয়াইটস্পেসের অক্ষর আইএফএসের মান হয় (একটি আইএফএস হোয়াইটস্পেস অক্ষর)। কোন চরিত্র IFS নয় Ifs হোয়াইটস্পেস কোনো সন্নিহিত সহ IFS হোয়াইটস্পেস অক্ষর, একটি ক্ষেত্র delimits। আইএফএস সাদা স্থানের অক্ষরের একটি অনুক্রমকেও একটি ডিলিমিটার হিসাবে বিবেচনা করা হয়। যদি আইএফএসের মান নাল হয় তবে কোনও শব্দ বিভাজন ঘটে না।
মূলত, অ-ডিফল্ট নন-নাল মানগুলির জন্য $IFS
, ক্ষেত্রগুলিকে (1) এক বা একাধিক অক্ষরের ক্রম দিয়ে পৃথক করা যায় যা সমস্ত "আইএফএস হোয়াইটস্পেস অক্ষর" এর সেট থেকে থাকে (যা <স্পেস>> এর যে কোনওটি , <tab> , এবং <নিউলাইন> ("নিউলাইন" অর্থ লাইন ফিড (এলএফ) ) যে কোনও জায়গায় উপস্থিত রয়েছে$IFS
), বা (২) $IFS
"আইএফএস হোয়াইটস্পেস অক্ষর" এর চারপাশে থাকা যে কোনও অ-"আইএফএস হোয়াইটস্পেস অক্ষর" উপস্থিত রয়েছে ইনপুট লাইনে।
ওপি'র পক্ষে এটি সম্ভবত সম্ভব যে পূর্বের অনুচ্ছেদে আমি বর্ণিত দ্বিতীয় বিচ্ছেদ মোডটি তার ইনপুট স্ট্রিংয়ের জন্য ঠিক যা চায়, তবে আমরা যথেষ্ট আত্মবিশ্বাসের সাথে বলতে পারি যে আমি বর্ণিত প্রথম বিচ্ছেদ মোডটি মোটেই সঠিক নয়। উদাহরণস্বরূপ, যদি তার ইনপুট স্ট্রিংটি ছিল 'Los Angeles, United States, North America'
?
IFS=', ' read -ra a <<<'Los Angeles, United States, North America'; declare -p a;
## declare -a a=([0]="Los" [1]="Angeles" [2]="United" [3]="States" [4]="North" [5]="America")
2: এমনকি যদি আপনি এই সমাধানটি একটি একক-অক্ষর বিভাজক (যেমন নিজেই একটি কমা হিসাবে, যে কোনও নিম্নলিখিত স্থান বা অন্যান্য ব্যাগেজ সহ) ব্যবহার করেন না, তবে যদি $string
ভেরিয়েবলের মানটি কোনও এলএফ থাকে তবে তা read
হবে একবার প্রথম এলএফ-এর মুখোমুখি হওয়ার পরে প্রক্রিয়াজাতকরণ বন্ধ করুন। read
Builtin শুধুমাত্র আবাহন প্রতি এক লাইন প্রক্রিয়া করে। এই সত্য এমনকি যদি আপনি বংশীধ্বনিতুল্য হয় বা ইনপুট পুনঃনির্দেশিত শুধুমাত্র করতে read
বিবৃতি, যেমন আমরা এই উদাহরণে করছ এখানে স্ট্রিং প্রক্রিয়া, এবং এইভাবে অপ্রক্রিয়াজাত ইনপুট হারিয়ে যেতে নিশ্চিত করা হয়। কোড যে শক্তিread
বিল্টিনকে কোডটিতে এর সাথে থাকা কমান্ড কাঠামোর মধ্যে ডেটা প্রবাহ সম্পর্কে কোনও জ্ঞান নেই।
আপনি তর্ক করতে পারেন যে এটি কোনও সমস্যার কারণ হতে পারে না তবে তবুও এটি একটি সূক্ষ্ম ঝুঁকি যা সম্ভব হলে এড়ানো উচিত। এটা সত্য যে দ্বারা ঘটিত হয় read
তারপর ক্ষেত্রগুলির মধ্যে লাইন প্রথম: builtin আসলে ইনপুট বিভাজন দুই মাত্রা আছে। যেহেতু ওপি কেবল একটি মাত্রার বিভাজন চায়, তাই read
বিল্টিনের এই ব্যবহারটি যথাযথ নয় এবং আমাদের এটি এড়ানো উচিত।
3: এই সমাধান সহ একটি অ-স্পষ্ট সম্ভাব্য সমস্যা হ'ল read
এটি খালি থাকলে সর্বদা অনুসরণের ক্ষেত্রটি ফেলে দেয়, যদিও এটি অন্যথায় খালি ক্ষেত্রগুলি সংরক্ষণ করে। এখানে একটি ডেমো রয়েছে:
string=', , a, , b, c, , , '; IFS=', ' read -ra a <<<"$string"; declare -p a;
## declare -a a=([0]="" [1]="" [2]="a" [3]="" [4]="b" [5]="c" [6]="" [7]="")
সম্ভবত ওপি এই বিষয়ে চিন্তা করবে না, তবে এটি সম্পর্কে জানার একটি সীমাবদ্ধতা এখনও রয়েছে। এটি সমাধানের দৃ rob়তা এবং সাধারণতা হ্রাস করে।
এই সমস্যাটি ডামি ট্রেইলিং ডিলিমিটারটিকে খাওয়ানোর ঠিক আগে ইনপুট স্ট্রিংয়ে যুক্ত করে সমাধান করা যেতে পারে read
, কারণ আমি পরে প্রদর্শন করব।
ভুল উত্তর # 2
string="1:2:3:4:5"
set -f # avoid globbing (expansion of *).
array=(${string//:/ })
অনুরূপ ধারণা:
t="one,two,three"
a=($(echo $t | tr ',' "\n"))
(দ্রষ্টব্য: কমান্ড প্রতিস্থাপনের আশেপাশে আমি অনুপস্থিত প্রথম বন্ধনী যুক্ত করেছি যা উত্তরদাতাকে বাদ দেওয়া হয়েছে বলে মনে হয়))
অনুরূপ ধারণা:
string="1,2,3,4"
array=(`echo $string | sed 's/,/\n/g'`)
এই সমাধানগুলি ক্ষেত্রগুলিতে স্ট্রিংকে বিভক্ত করার জন্য একটি অ্যারের অ্যাসাইনমেন্টে শব্দ বিভাজনকে উত্তোলন করে। মজাদারভাবে যথেষ্ট, ঠিক যেমন read
, সাধারণ শব্দ বিভাজনও $IFS
বিশেষ পরিবর্তনশীল ব্যবহার করে , যদিও এই ক্ষেত্রে এটি সূচিত হয় যে এটি <space><tab> <নিউলাইন> এর ডিফল্ট মানতে সেট করা আছে এবং সুতরাং এক বা একাধিক আইএফএসের যে কোনও অনুক্রম রয়েছে to অক্ষর (যা এখন সমস্ত শ্বেতক্ষেত্রের অক্ষর) ফিল্ড ডিলিমিটার হিসাবে বিবেচিত হয়।
এটি দ্বারা বিভক্ত দুটি স্তরের বিভক্তির সমস্যা সমাধান করে read
, যেহেতু শব্দ বিভাজন নিজেই বিভাজনের মাত্র একটি স্তরকে গঠন করে। তবে ঠিক আগের মতোই এখানে সমস্যাটি হ'ল ইনপুট স্ট্রিংয়ের পৃথক ক্ষেত্রগুলিতে ইতিমধ্যে $IFS
অক্ষর থাকতে পারে এবং এভাবে শব্দ বিভাজন ক্রিয়াকলাপের সময় তারা ভুলভাবে বিভক্ত হবে। এই উত্তরদাতারা প্রদত্ত কোনও নমুনা ইনপুট স্ট্রিংয়ের ক্ষেত্রে এটি না হওয়ার ঘটনা ঘটে (কতটা সুবিধাজনক ...) তবে অবশ্যই এই সত্যটি পরিবর্তিত হয় না যে এই আইডিয়ামটি ব্যবহার করে এমন কোনও কোড বেস এর ঝুঁকিটি চালিয়ে দেবে যদি এই ধারনাটি কখনও লাইন থেকে কিছুটা নীচে লঙ্ঘিত হয় তবে উড়িয়ে দেওয়া। আবার, 'Los Angeles, United States, North America'
(বা।) এর জবাবদিহি বিবেচনা করুন'Los Angeles:United States:North America'
) ।
এছাড়াও, শব্দ বিভাজন স্বাভাবিকভাবে দ্বারা অনুসরণ করা হয় ফাইলের নাম সম্প্রসারণ ( ওরফে পথনাম সম্প্রসারণ ওরফে , যা, যদি সম্পন্ন হলে, অক্ষর ধারণকারী সম্ভাব্য দুর্নীতিগ্রস্ত শব্দ হবে globbing) *
, ?
অথবা [
দ্বারা অনুসরণ ]
(এবং, যদি extglob
সেট করা থাকে, আলাদা টুকরা পূর্বে ?
, *
, +
, @
, বা !
) ফাইল সিস্টেমের সামগ্রীর সাথে তাদের মিলিয়ে এবং সেই অনুযায়ী শব্দগুলি ("গ্লোবস") প্রসারিত করে। এই তিন জন উত্তরদাতার মধ্যে প্রথমটি চূড়ান্তভাবে set -f
গ্লোব্বিং নিষ্ক্রিয় করতে আগে থেকে চালিয়ে এই সমস্যাটি স্বীকার করেছে। প্রযুক্তিগতভাবে এটি কাজ করে (যদিও আপনার সম্ভবত যোগ করা উচিতset +f
পরবর্তীকালে পরবর্তী কোডগুলির জন্য এটি পুনরায় সক্ষম করা সম্ভব হবে যা এটির উপর নির্ভর করে) তবে স্থানীয় কোডে একটি মৌলিক স্ট্রিং-টু-অ্যারে পার্সিং অপারেশন হ্যাক করতে গ্লোবাল শেল সেটিংসের সাথে জগাখিচুড়ি করা অনাকাঙ্ক্ষিত।
এই উত্তর সহ অন্য একটি সমস্যা হ'ল সমস্ত খালি ক্ষেত্র নষ্ট হবে। এটি প্রয়োগের উপর নির্ভর করে সমস্যা হতে পারে বা নাও হতে পারে।
দ্রষ্টব্য: আপনি যদি এই সমাধানটি ব্যবহার করতে চলেছেন তবে একটি পাইপলাইন শুরু করে, কমান্ড প্রতিস্থাপন (যা শেলটি কাঁটাচ্ছে) আহ্বান করার সমস্যায় না গিয়ে প্যারামিটার বিস্তারের${string//:/ }
"প্যাটার্ন প্রতিস্থাপন" ফর্মটি ব্যবহার করা ভাল and বাহ্যিক এক্সিকিউটেবল ( বা ) চালানো, যেহেতু প্যারামিটারের বিস্তৃতি নিখুঁতভাবে একটি শেল-অভ্যন্তরীণ অপারেশন। (এছাড়াও, এবং সমাধানগুলির জন্য, ইনপুট ভেরিয়েবলটি কমান্ড প্রতিস্থাপনের ভিতরে ডাবল-কোট করা উচিত; অন্যথায় শব্দ বিভাজন কমান্ডে কার্যকর হবে এবং ক্ষেত্রের মানগুলির সাথে সম্ভবত গণ্ডগোল হবে Also এছাড়াও, কমান্ড প্রতিস্থাপনের রূপটি পুরানোের চেয়ে পছন্দনীয়tr
sed
tr
sed
echo
$(...)
`...`
এটি কমান্ড বিকল্পের নেস্টিং সহজতর করে এবং পাঠ্য সম্পাদকদের দ্বারা আরও ভাল সিনট্যাক্স হাইলাইট করার অনুমতি দেয় form
ভুল উত্তর # 3
str="a, b, c, d" # assuming there is a space after ',' as in Q
arr=(${str//,/}) # delete all occurrences of ','
এই উত্তরটি প্রায় # 2 এর মতো । পার্থক্যটি হ'ল উত্তরদাতা এই ধারণাটি তৈরি করেছেন যে ক্ষেত্রগুলি দুটি অক্ষর দ্বারা সীমিত করা হয়েছে, যার মধ্যে একটি ডিফল্টরূপে প্রতিনিধিত্ব করা হচ্ছে $IFS
এবং অন্যটি নয়। তিনি এই আইটিএস-প্রতিনিধিত্বমূলক অক্ষরটিকে প্যাটার্ন প্রতিস্থাপনের প্রসারণ ব্যবহার করে এবং তারপরে বেঁচে থাকা আইএফএস-প্রতিনিধিত্বকারী ডিলিমিটার চরিত্রের ক্ষেত্রগুলিকে বিভক্ত করার জন্য শব্দ বিভাজন ব্যবহার করে বরং এই নির্দিষ্ট ক্ষেত্রে সমাধান করেছেন।
এটি খুব জেনেরিক সমাধান নয়। তদ্ব্যতীত, এটি যুক্তিযুক্ত হতে পারে যে কমাটি এখানে প্রকৃতপক্ষে "প্রাথমিক" ডিলিমিটার চরিত্র এবং এটি কেড়ে ফেলা এবং তারপরে ক্ষেত্র বিভাজনের জন্য স্থানের অক্ষরের উপর নির্ভর করে কেবল ভুল। আবার, আমার counterexample বিবেচনা করুন: 'Los Angeles, United States, North America'
।
এছাড়াও, আবার ফাইল নাম প্রসারিত প্রসারিত শব্দগুলিকে দূষিত করতে পারে তবে অ্যাসাইনমেন্টের জন্য অস্থায়ীভাবে গ্লোব্বিং অক্ষম করে set -f
এবং এরপরে এটি প্রতিরোধ করা যেতে পারে set +f
।
এছাড়াও, আবার, সমস্ত খালি ক্ষেত্রগুলি হারিয়ে যাবে, যা অ্যাপ্লিকেশনটির উপর নির্ভর করে সমস্যা হতে পারে বা নাও পারে।
ভুল উত্তর # 4
string='first line
second line
third line'
oldIFS="$IFS"
IFS='
'
IFS=${IFS:0:1} # this is useful to format your code with tabs
lines=( $string )
IFS="$oldIFS"
এটি # 2 এবং এর মতো # 3 এর যে এটি কাজটি করতে শব্দ বিভাজন ব্যবহার করে, কেবল এখন কোডটি স্পষ্টভাবে $IFS
ইনপুট স্ট্রিংয়ে উপস্থিত কেবল একক-অক্ষর ক্ষেত্রের ডিলিমেটার ধারণ করে। এটি পুনরাবৃত্তি করা উচিত যে এটি ওপি'র কমা-স্পেস ডিলিমিটারের মতো মাল্টিচার্যাক্টর ফিল্ড ডিলিমিটারগুলির পক্ষে কাজ করতে পারে না। তবে এই উদাহরণে ব্যবহৃত এলএফ এর মতো একক-চরিত্রের ডিলিমিটারের জন্য এটি আসলে নিখুঁত হওয়ার কাছাকাছি আসে। পূর্বের ভুল উত্তরের সাহায্যে ক্ষেত্রগুলি অজান্তেই বিভক্ত করা যায় না এবং প্রয়োজন অনুসারে বিভক্তির মাত্র এক স্তর রয়েছে।
একটি সমস্যা হ'ল ফাইলের নাম সম্প্রসারণ পূর্বের বর্ণিত হিসাবে ক্ষতিগ্রস্থ শব্দগুলিকে দূষিত করবে, যদিও এর পরে আবারও সমালোচনামূলক বিবৃতিটি গুটিয়ে রেখে সমাধান করা যেতে পারে set -f
এবং set +f
।
আর একটি সম্ভাব্য সমস্যা হ'ল, এলএফ যেহেতু পূর্বনির্ধারিত হিসাবে "আইএফএস হোয়াইটস্পেস চরিত্র" হিসাবে যোগ্যতা অর্জন করেছে, সমস্ত খালি ক্ষেত্রগুলি হারিয়ে যাবে, ঠিক যেমন # 2 এবং # 3 । এটি অবশ্যই কোনও সমস্যা হবে না যদি ডিলিমিটারটি একটি "আইএফএস হোয়াইটস্পেসের অক্ষরবিহীন অক্ষর" হয়ে থাকে এবং প্রয়োগের উপর নির্ভর করে এটি কোনওভাবেই গুরুত্বপূর্ণ না, তবে এটি সমাধানের সাধারণতাটিকে বিকৃত করে তোলে।
সুতরাং, সংক্ষেপে, আপনার এক-চরিত্রের ডিলিমিটার রয়েছে বলে ধরে নেওয়া এবং এটি হয় একটি "অ-আইএফএস হোয়াইটস্পেস অক্ষর" বা আপনি খালি ক্ষেত্রের যত্ন নেই, এবং আপনি সমালোচনামূলক বিবৃতিটি মুড়ে দিন set -f
এবংset +f
তারপরে এই সমাধানটি কার্যকর হয় , কিন্তু অন্যথায় না।
(এছাড়াও তথ্যের স্বার্থে, ব্যাশে ভেরিয়েবলের জন্য একটি এলএফ বরাদ্দকরণ $'...'
বাক্য বাক্সের সাহায্যে আরও সহজে করা যায় , যেমন eg IFS=$'\n';
)
ভুল উত্তর # 5
countries='Paris, France, Europe'
OIFS="$IFS"
IFS=', ' array=($countries)
IFS="$OIFS"
অনুরূপ ধারণা:
IFS=', ' eval 'array=($string)'
এই সমাধানটি কার্যকরভাবে # 1 এর মধ্যে ক্রস (যাতে এটি $IFS
কমা-স্পেসে সেট হয়) এবং # 2-4 (এর মধ্যে এটি স্ট্রিংকে ক্ষেত্রগুলিতে বিভক্ত করতে শব্দ বিভাজন ব্যবহার করে)। এর কারণে, এটি উপরের সমস্ত ভুল উত্তরকে যে বেশিরভাগ সমস্যায় ভোগায় তা বেশিরভাগ সমস্যায় ভুগছে, বাছাই করা সমস্ত বিশ্বের সবচেয়ে খারাপের মতো like
এছাড়াও, দ্বিতীয় বৈকল্পিক সম্পর্কিত, eval
কলটি সম্পূর্ণ অপ্রয়োজনীয় বলে মনে হতে পারে , যেহেতু এর যুক্তিটি একটি একক-উদ্ধৃত স্ট্রিং আক্ষরিক, এবং তাই এটি স্থিতিশীলভাবে পরিচিত। তবে আসলে eval
এইভাবে ব্যবহার করার জন্য একটি খুব অ-সুস্পষ্ট সুবিধা রয়েছে । সাধারণত, আপনি যখন একটি সাধারণ কমান্ড চালান যা কেবলমাত্র একটি চলক অ্যাসাইনমেন্ট ধারণ করে , যার অর্থ আসল কমান্ড শব্দটি অনুসরণ না করে, শেল পরিবেশে অ্যাসাইনমেন্টটি কার্যকর হয়:
IFS=', '; ## changes $IFS in the shell environment
সরল কমান্ডে একাধিক ভেরিয়েবল অ্যাসাইনমেন্ট যুক্ত থাকলেও এটি সত্য ; আবার, যতক্ষণ না কোনও কমান্ড শব্দ নেই, সমস্ত পরিবর্তনশীল অ্যাসাইনমেন্ট শেল পরিবেশকে প্রভাবিত করে:
IFS=', ' array=($countries); ## changes both $IFS and $array in the shell environment
তবে, যদি ভেরিয়েবল অ্যাসাইনমেন্টটি কমান্ড নামের সাথে সংযুক্ত থাকে (আমি এটিকে "উপসর্গ অ্যাসাইনমেন্ট" বলতে চাই) তবে এটি শেল পরিবেশের উপর প্রভাব ফেলবে না এবং পরিবর্তে কেবল নির্বাহী কমান্ডের পরিবেশকে প্রভাবিত করবে, নির্বিশেষে এটি বিল্টিনই হোক না কেন বা বাহ্যিক:
IFS=', ' :; ## : is a builtin command, the $IFS assignment does not outlive it
IFS=', ' env; ## env is an external command, the $IFS assignment does not outlive it
বাশ ম্যানুয়াল থেকে প্রাসঙ্গিক উক্তি :
যদি কোনও কমান্ড নাম ফলাফল না করে, ভেরিয়েবল অ্যাসাইনমেন্টগুলি বর্তমান শেল পরিবেশকে প্রভাবিত করে। অন্যথায়, ভেরিয়েবলগুলি এক্সিকিউটড কমান্ডের পরিবেশে যুক্ত হয় এবং বর্তমান শেল পরিবেশকে প্রভাবিত করে না।
$IFS
কেবলমাত্র অস্থায়ীভাবে পরিবর্তনের জন্য ভেরিয়েবল অ্যাসাইনমেন্টের এই বৈশিষ্ট্যটি কাজে লাগানো সম্ভব যা $OIFS
প্রথম ভেরিয়েবলের সাথে ভেরিয়েবলের সাহায্যে সম্পূর্ণ সেভ-অ্যান্ড-রিস্টোর গাম্বিটকে এড়াতে দেয় । তবে আমরা এখানে যে চ্যালেঞ্জের মুখোমুখি হই তা হ'ল আমাদের যে কমান্ডটি চালাতে হবে তা হ'ল একটি নিছক পরিবর্তনশীল অ্যাসাইনমেন্ট এবং তাই এই $IFS
অ্যাসাইনমেন্টটি অস্থায়ী করার জন্য কোনও আদেশ আদেশ জড়িত না । আপনি নিজেই ভাবতে পারেন, ভাল কেন অস্থায়ী : builtin
করার জন্য যেমন বিবৃতিতে কোনও অপ-কমান্ড শব্দ যুক্ত করবেন না $IFS
? এটি কাজ করে না কারণ এরপরে $array
অ্যাসাইনমেন্টটিও অস্থায়ী করে তুলবে :
IFS=', ' array=($countries) :; ## fails; new $array value never escapes the : command
সুতরাং, আমরা কার্যকরভাবে একটি অচলাবস্থায়, কিছুটা ধরা -২২। তবে, যখন eval
তার কোডটি চালায় এটি শেল পরিবেশে এটি চালায়, যেন এটি সাধারণ, স্থির উত্স কোড এবং তাই শেল পরিবেশে কার্যকর হওয়ার জন্য আমরা আর্গুমেন্টের $array
ভিতরে অ্যাসাইনমেন্টটি চালাতে পারি eval
, যখন $IFS
উপসর্গের অ্যাসাইনমেন্টটি eval
কমান্ডের পূর্বনির্ধারিত কমান্ডটি বহিরাগত হবে না eval
। এই সমাধানটির দ্বিতীয় ধরণেরটিতে হ'ল কৌশলটি হ'ল:
IFS=', ' eval 'array=($string)'; ## $IFS does not outlive the eval command, but $array does
সুতরাং, আপনি দেখতে পাচ্ছেন যে এটি আসলে একটি চতুর কৌশল এবং এটি অপ্রত্যাশিত উপায়ে সঠিকভাবে প্রয়োজনীয় যা প্রয়োজন (কমপক্ষে অন্তর্ভুক্তির কার্যপ্রণালীকরণের ক্ষেত্রে) আমি জড়িত থাকার পরেও আসলে এই কৌশলটির বিরুদ্ধে নই eval
; সুরক্ষা হুমকির বিরুদ্ধে রক্ষা করার জন্য কেবল যুক্তি স্ট্রিংয়ের একক-উদ্ধৃতি দিতে সাবধান হন।
তবে আবার, "সমস্ত পৃথিবীর মধ্যে সবচেয়ে খারাপ" সমস্যার উত্থানের কারণে এটি এখনও ওপি-র প্রয়োজনীয়তার একটি ভুল উত্তর answer
ভুল উত্তর # 6
IFS=', '; array=(Paris, France, Europe)
IFS=' ';declare -a array=(Paris France Europe)
উম ... কি? ওপিতে একটি স্ট্রিং ভেরিয়েবল রয়েছে যা অ্যারেতে পার্স করা দরকার। এই "উত্তর" আরে আক্ষরিক মধ্যে আটকানো ইনপুট স্ট্রিংয়ের ভারব্যাটিম বিষয়বস্তু দিয়ে শুরু হয়। আমার ধারণা এটি করার এক উপায় one
দেখে মনে হচ্ছে যা উত্তরদাতা ধরে নিয়েছে যে $IFS
ভেরিয়েবলটি সমস্ত প্রসঙ্গে সমস্ত ব্যাশ পার্সিংকে প্রভাবিত করে, যা সত্য নয়। বাশ ম্যানুয়াল থেকে:
আইএফএস অভ্যন্তরীণ ক্ষেত্র বিভাজক যা প্রসারণের পরে শব্দ বিভাজনের জন্য এবং পঠিত বিল্টিন কমান্ডের সাহায্যে শব্দের মধ্যে লাইনগুলি বিভক্ত করতে ব্যবহৃত হয় । ডিফল্ট মান হ'ল <স্পেস> << ট্যাব> <নিউলাইন> ।
সুতরাং $IFS
বিশেষ পরিবর্তনশীলটি কেবলমাত্র দুটি প্রসঙ্গে ব্যবহৃত হয়: (1) শব্দ বিভাজন যা প্রসারণের পরে সঞ্চালিত হয় (যার অর্থ ব্যাশ উত্স কোডটি পার্সিং করার সময় নয় ) এবং (2) read
বিল্টিন দ্বারা শব্দগুলিতে ইনপুট লাইনগুলি বিভক্ত করার জন্য ।
আমাকে এই পরিষ্কার করার চেষ্টা করুন। আমি মনে করি পার্সিং এবং কার্যকর করার মধ্যে পার্থক্য আঁকতে ভাল হতে পারে । ব্যাশ প্রথম আবশ্যক পার্স সোর্স কোড, যা সম্ভবত হয় পার্সিং ঘটনা, এবং তারপর পরে executes কোড, যা যখন সম্প্রসারণ ছবি আসে। সম্প্রসারণ সত্যিই একটি বাস্তবায়ন ইভেন্ট। তদুপরি, আমি $IFS
ভেরিয়েবলের বিবরণ দিয়ে বিষয়টি নিয়েছি যা আমি উপরে উপরে উদ্ধৃত করেছি; শব্দের বিভাজনটি প্রসারণের পরে সঞ্চালিত হওয়ার পরিবর্তে আমি বলব যে শব্দ বিভাজনটি প্রসারণের সময় সঞ্চালিত হয় বা সম্ভবত আরও স্পষ্টভাবে বলতে গেলে শব্দ বিভাজন হয় অংশসম্প্রসারণ প্রক্রিয়া। "শব্দ বিভাজন" শব্দগুচ্ছটি কেবল প্রসারিত এই পদক্ষেপকে বোঝায়; এটি কখনই ব্যাশ উত্স কোডটি বিশ্লেষণের জন্য ব্যবহার করা উচিত নয়, যদিও দুর্ভাগ্যক্রমে ডকগুলি "বিভাজন" এবং "শব্দ" শব্দের প্রচুর পরিমাণে ফেলেছে বলে মনে হয়। বাশ ম্যানুয়ালটির linux.die.net সংস্করণ থেকে একটি প্রাসঙ্গিক অংশ এখানে দেওয়া হয়েছে :
কমান্ড লাইনে এটি শব্দগুলিতে বিভক্ত হওয়ার পরে সম্প্রসারণ করা হয়। এখানে সাত ধরণের সম্প্রসারণ করা হয়: ব্রেস এক্সপেনশন , টিলডে এক্সপেনশন , প্যারামিটার এবং ভেরিয়েবল এক্সপেনশন , কমান্ড সাবস্টিটিউশন , পাটিগণিত সম্প্রসারণ , শব্দ বিভাজন এবং পথের নাম সম্প্রসারণ ।
বিস্তারের ক্রম: ব্রেস সম্প্রসারণ; টিলডে সম্প্রসারণ, প্যারামিটার এবং পরিবর্তনশীল সম্প্রসারণ, পাটিগণিতের সম্প্রসারণ এবং কমান্ড প্রতিস্থাপন (বাম থেকে ডান ফ্যাশনে সম্পন্ন); শব্দ বিভাজন; এবং পথের নাম সম্প্রসারণ।
আপনি ম্যানুয়ালটির জিএনইউ সংস্করণটি কিছুটা ভাল করতে পারেন, কারণ এটি সম্প্রসারণ বিভাগের প্রথম বাক্যে "শব্দের" পরিবর্তে "টোকেন" শব্দের জন্য বেছে নেওয়া হয়েছে:
কমান্ড লাইনে টোকেনে বিভক্ত হওয়ার পরে সম্প্রসারণ করা হয়।
গুরুত্বপূর্ণ বিষয়টি হ'ল $IFS
বাশ সোর্স কোডকে পার্স করার উপায় পরিবর্তন করে না। বাশ উত্স কোড পার্সিং আসলে একটি খুব জটিল প্রক্রিয়া যার মধ্যে শেল ব্যাকরণের বিভিন্ন উপাদান যেমন কমান্ড সিকোয়েন্সস, কমান্ড তালিকাগুলি, পাইপলাইনগুলি, প্যারামিটার সম্প্রসারণ, পাটিগণিতের বিকল্প এবং কমান্ড বিকল্পের স্বীকৃতি জড়িত। বেশিরভাগ ক্ষেত্রে, ব্যাশ পার্সিং প্রক্রিয়াটি ভেরিয়েবল অ্যাসাইনমেন্টের মতো ব্যবহারকারী-স্তরের ক্রিয়া দ্বারা পরিবর্তন করা যায় না (আসলে, এই নিয়মের কিছু ছোট ব্যতিক্রম রয়েছে; উদাহরণস্বরূপ, বিভিন্নটি দেখুনcompatxx
শেল সেটিংস দেখুন, যা ফ্লাইটে পার্সিং আচরণের নির্দিষ্ট কিছু দিক পরিবর্তন করতে পারে)। এই জটিল বিশ্লেষণ প্রক্রিয়া থেকে প্রাপ্ত প্রবাহিত "শব্দ" / "টোকেন" এরপরে উপরের ডকুমেন্টেশন অংশগুলিতে ভাঙা হিসাবে "সম্প্রসারণ" এর সাধারণ প্রক্রিয়া অনুসারে প্রসারিত হয়, যেখানে প্রসারিত (প্রসারিত?) পাঠ্যের শব্দ বিভাজনকে নিম্ন প্রবাহে বিভক্ত করা হয় শব্দগুলি কেবল সেই প্রক্রিয়াটির একটি পদক্ষেপ। শব্দ বিভাজন কেবল এমন পাঠ্যকে স্পর্শ করে যা পূর্ববর্তী বিস্তৃত পদক্ষেপের বাইরে থুথু ফেলেছে; এটি আক্ষরিক পাঠ্যকে প্রভাবিত করে না যা উত্স বাইস্ট্রিমে সরাসরি পার্স করা হয়েছিল।
ভুল উত্তর # 7
string='first line
second line
third line'
while read -r line; do lines+=("$line"); done <<<"$string"
এটি সেরা সমাধানগুলির মধ্যে একটি। লক্ষ্য করুন যে আমরা ব্যবহার করতে ফিরে এসেছি read
। আমি কি আগে বলিনি যে read
এটি অনুপযুক্ত কারণ এটি দুটি স্তরের বিভাজন করে, যখন আমাদের কেবল একটি প্রয়োজন? এখানে কৌশলটি আপনি read
এইভাবে কল করতে পারেন যে এটি কার্যকরভাবে কেবলমাত্র এক স্তরের বিভাজন করে, বিশেষত অনুরোধ অনুসারে কেবলমাত্র একটি ক্ষেত্র বিভক্ত করে, যা বার বার লুপে ফোন করার জন্য প্রয়োজনীয় খরচ প্রয়োজন। এটি কিছুটা হাতের মুঠোয়, তবে এটি কার্যকর।
তবে সমস্যা আছে। প্রথম: আপনি যখন কমপক্ষে একটি NAME আর্গুমেন্ট সরবরাহ করেন read
, তখন এটি স্বয়ংক্রিয়ভাবে প্রতিটি ক্ষেত্রের শীর্ষস্থানীয় এবং পিছনের শ্বেত স্পেসটিকে উপেক্ষা করে যা ইনপুট স্ট্রিং থেকে বিচ্ছিন্ন। $IFS
এই পোস্টে আগে বর্ণিত হিসাবে এটির ডিফল্ট মানতে সেট করা আছে কি না তা ঘটে । এখন, ওপি তার নির্দিষ্ট ব্যবহারের ক্ষেত্রে এটি সম্পর্কে চিন্তা করবে না এবং আসলে এটি পার্সিং আচরণের একটি পছন্দসই বৈশিষ্ট্য হতে পারে। তবে যে ক্ষেত্রগুলিতে কোনও স্ট্রিংকে বিশ্লেষণ করতে চায় তারা সকলেই এটি চাইবে না। তবে এর একটি সমাধান রয়েছে: read
শূন্য NAME আর্গুমেন্টগুলি পাস করার জন্য কিছুটা অপ্রকাশিত ব্যবহার । এই ক্ষেত্রে, read
পুরো ইনপুট লাইনটি এটি ইনপুট স্ট্রিম থেকে পাওয়া ভেরিয়েবেলে সংরক্ষণ করবে $REPLY
এবং একটি বোনাস হিসাবে, এটি নামান থেকে স্ট্রিপ শীর্ষস্থানীয় এবং পিছনে সাদা স্থান। এটি একটি অত্যন্ত শক্তিশালী ব্যবহার read
যা আমি আমার শেল প্রোগ্রামিং ক্যারিয়ারে ঘন ঘন শোষণ করেছি। আচরণের পার্থক্যের একটি প্রদর্শন এখানে দেওয়া হয়েছে:
string=$' a b \n c d \n e f '; ## input string
a=(); while read -r line; do a+=("$line"); done <<<"$string"; declare -p a;
## declare -a a=([0]="a b" [1]="c d" [2]="e f") ## read trimmed surrounding whitespace
a=(); while read -r; do a+=("$REPLY"); done <<<"$string"; declare -p a;
## declare -a a=([0]=" a b " [1]=" c d " [2]=" e f ") ## no trimming
এই সমাধানটির সাথে দ্বিতীয় ইস্যুটি হ'ল এটি কোনও কাস্টম ফিল্ড বিভাজকের ক্ষেত্রে যেমন ওপি'র কমা-স্পেসের ক্ষেত্রে সমাধান করে না। আগের মতো, মাল্টিচার্যাক্টর বিভাজকগুলি সমর্থিত নয়, যা এই সমাধানের দুর্ভাগ্যজনক সীমাবদ্ধতা। -d
বিকল্পটিতে পৃথককারী নির্দিষ্ট করে আমরা কমপক্ষে কমপক্ষে বিভক্ত হওয়ার চেষ্টা করতে পারি , তবে কী ঘটে তা দেখুন:
string='Paris, France, Europe';
a=(); while read -rd,; do a+=("$REPLY"); done <<<"$string"; declare -p a;
## declare -a a=([0]="Paris" [1]=" France")
অনুমানযোগ্যভাবে, অ্যাকাউন্টহীন আশেপাশের শ্বেতস্থানটি ক্ষেত্রের মানগুলিতে টান পড়েছে, এবং তাই এটি পরে ছাঁটাইয়ের ক্রিয়াকলাপগুলির মাধ্যমে সংশোধন করতে হবে (এটি সরাসরি লুপ-লুপেও করা যেতে পারে)। তবে আরও একটি স্পষ্ট ত্রুটি আছে: ইউরোপ অনুপস্থিত! এটা কি হয়েছে? উত্তরটি হ'ল read
যদি একটি চূড়ান্ত ক্ষেত্রের চূড়ান্ত ক্ষেত্রের টার্মিনেটরের মুখোমুখি না হয়ে ফাইলের শেষের দিকে (এই ক্ষেত্রে আমরা এটিকে স্ট্রিং-এর স্ট্রিং বলতে পারি) আঘাত করে তবে একটি ব্যর্থ রিটার্ন কোড দেয় returns এর ফলে অল্প সময়ের মধ্যে লুপটি ভেঙে যায় এবং আমরা চূড়ান্ত ক্ষেত্রটি হারাতে পারি।
প্রযুক্তিগতভাবে এই একই ত্রুটি পূর্ববর্তী উদাহরণগুলিকেও ক্ষতিগ্রস্থ করেছিল; পার্থক্যটি হ'ল ক্ষেত্র বিভাজককে এলএফ হিসাবে নেওয়া হয়েছিল, আপনি -d
অপশনটি নির্দিষ্ট না করার সময় এটি ডিফল্ট এবং <<<
("এখানে-স্ট্রিং") প্রক্রিয়াটি নিজের মতো করে ফিড দেওয়ার ঠিক আগে স্ট্রিংয়ে একটি এলএফ সংযুক্ত করে app কমান্ড ইনপুট। অতএব, এই ক্ষেত্রে, আমরা বাছাই করে দুর্ঘটনাবশত ইনপুটটিতে অতিরিক্ত ডামি টার্মিনেটর যুক্ত করে অজ্ঞাতসারে বাদ পড়ে যাওয়া চূড়ান্ত ক্ষেত্রের সমস্যাটি সমাধান করেছি। আসুন আমরা এই সমাধানটিকে "ডামি-টার্মিনেটর" সমাধান বলি। আমরা এখানে স্ট্রিং-এ ইনস্ট্যান্ট করার সময় ডামি-টার্মিনেটর সমাধানটিকে যেকোন কাস্টম ডেলিমিটারের জন্য ম্যানুয়ালি প্রয়োগ করতে পারি against
a=(); while read -rd,; do a+=("$REPLY"); done <<<"$string,"; declare -p a;
declare -a a=([0]="Paris" [1]=" France" [2]=" Europe")
সেখানে, সমস্যার সমাধান হয়েছে। অন্য সমাধানটি হ'ল লুপটি কেবলমাত্র ভাঙা যদি উভয় (1) read
ব্যর্থতা ফিরে আসে এবং (2) $REPLY
খালি থাকে, মানে read
ফাইলের শেষের দিকে আঘাত করার আগে কোনও অক্ষর পড়তে সক্ষম হয় নি। ডেমো:
a=(); while read -rd,|| [[ -n "$REPLY" ]]; do a+=("$REPLY"); done <<<"$string"; declare -p a;
## declare -a a=([0]="Paris" [1]=" France" [2]=$' Europe\n')
এই পদ্ধতির মাধ্যমে গোপনীয় এলএফও প্রকাশিত হয় যা <<<
পুনঃনির্দেশ অপারেটর দ্বারা স্বয়ংক্রিয়ভাবে এখানে স্ট্রিংয়ে সংযুক্ত হয়ে যায় । কিছুক্ষণ আগে বর্ণিত স্পষ্ট ট্রিমিং অপারেশনের মাধ্যমে অবশ্যই এটি আলাদাভাবে ছিনিয়ে নেওয়া যেতে পারে তবে স্পষ্টতই ম্যানুয়াল ডামি-টার্মিনেটর পদ্ধতির এটি সরাসরি সমাধান করে, তাই আমরা কেবল এটির সাথে যেতে পারি। ম্যানুয়াল ডামি-টার্মিনেটর সমাধানটি আসলে বেশ সুবিধাজনক কারণ এটি একসাথে এই দুটি সমস্যা (বাদ পড়ে-চূড়ান্ত ক্ষেত্রের সমস্যা এবং সংযুক্ত-এলএফ সমস্যা) উভয়ই সমাধান করে।
সুতরাং, সামগ্রিকভাবে, এটি বেশ শক্তিশালী সমাধান। এটি কেবলমাত্র দূর্বলতা হ'ল মাল্টিচার্যাক্টার ডিলিমিটারদের জন্য সমর্থনের অভাব, যা আমি পরে উল্লেখ করব।
ভুল উত্তর # 8
string='first line
second line
third line'
readarray -t lines <<<"$string"
(এটি আসলে # 7 এর একই পোস্ট থেকে ; উত্তর পোস্টকারী একই পোস্টে দুটি সমাধান সরবরাহ করেছে))
readarray
Builtin, যার জন্য একটি প্রতিশব্দ হয় mapfile
, আদর্শ। এটি একটি বিল্টিন কমান্ড যা একটি শটে একটি অ্যারে ভেরিয়েবলের মধ্যে একটি বাইস্ট্রিমে পার্স করে; লুপস, শর্তসাপেক্ষ, বিকল্পগুলি বা অন্য কোনও কিছুর সাথে বিশৃঙ্খলা নেই। এবং এটি ইনপুট স্ট্রিং থেকে গোপনীয়ভাবে কোনও হোয়াইটস্পেস ছিনিয়ে নেবে না। এবং (যদি -O
দেওয়া না হয়) এটি নির্ধারিত হওয়ার আগে লক্ষ্য বিন্যাসটি সুবিধামত সাফ করে। তবে এটি এখনও নিখুঁত নয়, অতএব এটি আমার একটি "ভুল উত্তর" হিসাবে সমালোচনা।
প্রথমে, এটিকে বাইরে বের করার জন্য, খেয়াল করুন যে, read
ফিল্ড-পার্সিং করার সময় যেমন আচরণ করা হয়েছে readarray
ঠিক তেমন পেছনের ক্ষেত্রটি খালি থাকলে ফেলে দেয়। আবার এটি সম্ভবত ওপিটির জন্য উদ্বেগ নয়, তবে এটি কিছু ব্যবহারের ক্ষেত্রেও হতে পারে। আমি এই মুহুর্তে ফিরে আসতে হবে।
দ্বিতীয়ত, আগের মতো, এটি মাল্টিচার্যাক্টর ডিলিমিটারগুলিকে সমর্থন করে না। আমি এর জন্য একটি মুহূর্তের মধ্যেও একটি সংশোধন দেব।
তৃতীয়ত, লিখিত হিসাবে সমাধানটি ওপি-র ইনপুট স্ট্রিংকে বিশ্লেষণ করে না এবং বাস্তবে এটি পার্স করার জন্য এটি ব্যবহার করা যায় না। আমি এই মুহুর্তে পাশাপাশি প্রসারিত করব।
উপরের কারণগুলির জন্য, আমি এখনও এটিকে ওপি-র প্রশ্নের "ভুল উত্তর" হিসাবে বিবেচনা করি। নীচে আমি যা সঠিক উত্তর বলে মনে করি তা দেব give
সঠিক উত্তর
এখানে কেবলমাত্র বিকল্পটি উল্লেখ করে # 8 টি কাজ করার একটি নির্বুদ্ধ প্রচেষ্টা -d
:
string='Paris, France, Europe';
readarray -td, a <<<"$string"; declare -p a;
## declare -a a=([0]="Paris" [1]=" France" [2]=$' Europe\n')
আমরা দেখতে পাচ্ছি যে ফলাফলটি # 7-এread
আলোচিত লুপিং সমাধানের দ্বৈত-শর্তসাপেক্ষ দৃষ্টিভঙ্গি থেকে প্রাপ্ত ফলাফলের সাথে সমান । আমরা ম্যানুয়াল ডামি-টার্মিনেটর ট্রিক দিয়ে প্রায় এটি সমাধান করতে পারি :
readarray -td, a <<<"$string,"; declare -p a;
## declare -a a=([0]="Paris" [1]=" France" [2]=" Europe" [3]=$'\n')
এখানে সমস্যাটি হ'ল readarray
পিছনের ক্ষেত্রটি সংরক্ষণ করা হয়েছে , যেহেতু <<<
পুনর্নির্দেশ অপারেটর এলএফকে ইনপুট স্ট্রিংয়ে সংযুক্ত করেছিল, এবং সুতরাং পিছনের ক্ষেত্রটি খালি ছিল না (অন্যথায় এটি বাদ দেওয়া হত)। আমরা বাস্তবতার পরে চূড়ান্ত অ্যারে উপাদানটি সুস্পষ্টভাবে সেট করে এই যত্ন নিতে পারি:
readarray -td, a <<<"$string,"; unset 'a[-1]'; declare -p a;
## declare -a a=([0]="Paris" [1]=" France" [2]=" Europe")
কেবলমাত্র দুটি সমস্যা রয়ে গেছে যা আসলে সম্পর্কিত are (1) এক্সটেনারিয়াস হোয়াইটস্পেস যা ছাঁটাই করা দরকার, এবং (2) মাল্টিচ্যার্যাক্টর ডিলিমিটরদের সমর্থন সমর্থন নেই।
হোয়াইটস্পেস অবশ্যই পরে ছাঁটাই করা যেতে পারে (উদাহরণস্বরূপ, বাশ ভেরিয়েবল থেকে হোয়াইটস্পেসটি কীভাবে ছাঁটাবেন দেখুন? ) তবে আমরা যদি কোনও মাল্টিচার্যাক্টর ডিলিমিটার হ্যাক করতে পারি, তবে এটি উভয়ই এক শটে সমাধান করবে shot
দুর্ভাগ্যক্রমে, কোনও মাল্টিচার্যাক্টর ডিলিমিটারে কাজ করার সরাসরি কোনও উপায় নেই । আমি যে সর্বোত্তম সমাধানটির কথা ভেবেছি তা হ'ল মাল্টিচ্যার্যাক্টর ডিলিমেটারকে একক অক্ষর ডিলিমিটারের সাথে প্রতিস্থাপনের জন্য ইনপুট স্ট্রিংটিকে প্রিপ্রসেস করা যা ইনপুট স্ট্রিংয়ের বিষয়বস্তুগুলির সাথে সংঘর্ষ না হওয়ার গ্যারান্টিযুক্ত হবে। এই গ্যারান্টিটি সহ কেবলমাত্র অক্ষরটি হল NUL বাইট । এটি কারণ, ব্যাশে (যদিও zsh না হলেও, ঘটনাচক্রে), ভেরিয়েবলগুলিতে NUL বাইট থাকতে পারে না। প্রক্রিয়া প্রতিস্থাপনে এই প্রিপ্রোসেসিং পদক্ষেপটি ইনলাইন করা যায়। অ্যাডকে ব্যবহার করে এটি কীভাবে করা যায় তা এখানে :
readarray -td '' a < <(awk '{ gsub(/, /,"\0"); print; }' <<<"$string, "); unset 'a[-1]';
declare -p a;
## declare -a a=([0]="Paris" [1]="France" [2]="Europe")
সেখানে, অবশেষে! এই সমাধানটি ভুলভাবে মাঝখানে ক্ষেত্রগুলি বিভক্ত করবে না, অকালে কাটবে না, খালি ক্ষেত্রগুলি ফেলে দেবে না, ফাইলের নাম প্রসারণে নিজেকে দূষিত করবে না, স্বয়ংক্রিয়ভাবে শীর্ষস্থানীয় এবং অনুসরণকারী শ্বেতস্পেসকে ছাঁটাবে না, শেষের দিকে স্টোওয়ে এলএফ ছাড়বে না, লুপগুলির প্রয়োজন হয় না এবং একটি একক-অক্ষর ডিলিমিটারের জন্য স্থির হয় না।
ট্রিমিং সমাধান
অবশেষে, আমি এর নিজের অস্পষ্ট -C callback
বিকল্পটি ব্যবহার করে আমার নিজের মোটামুটি জটিলতর ট্রিমিং সমাধানটি প্রদর্শন করতে চেয়েছিলাম readarray
। দুর্ভাগ্যক্রমে, আমি স্ট্যাক ওভারফ্লোর 30,000 চরিত্রের পোস্টের সীমা ছাড়িয়ে গিয়েছি, তাই আমি এটি ব্যাখ্যা করতে পারব না। আমি পাঠকের জন্য অনুশীলন হিসাবে ছেড়ে দেব।
function mfcb { local val="$4"; "$1"; eval "$2[$3]=\$val;"; };
function val_ltrim { if [[ "$val" =~ ^[[:space:]]+ ]]; then val="${val:${#BASH_REMATCH[0]}}"; fi; };
function val_rtrim { if [[ "$val" =~ [[:space:]]+$ ]]; then val="${val:0:${#val}-${#BASH_REMATCH[0]}}"; fi; };
function val_trim { val_ltrim; val_rtrim; };
readarray -c1 -C 'mfcb val_trim a' -td, <<<"$string,"; unset 'a[-1]'; declare -p a;
## declare -a a=([0]="Paris" [1]="France" [2]="Europe")
,
কমা-মহাকাশ হিসাবে ডিলিট করার বিষয়ে জিজ্ঞাসা করে এবং কমা হিসাবে কোনও একক চরিত্র নয় । আপনি শুধুমাত্র আধুনিক করতে আগ্রহী হন তবে, উত্তর এখানে অনুসরণ করা সহজ হয়: stackoverflow.com/questions/918886/...