অন্যান্য উত্তর (যা বরং ঘন হয়) ভঙ্গ হবে যদি কমান্ডের আউটপুট স্পেস রয়েছে বা মত অক্ষর উল্লিখিত glob *
, ?
, [...]
।
অ্যারেতে কমান্ডের আউটপুট পেতে প্রতিটি উপাদানকে এক রেখার সাহায্যে প্রয়োজনীয় 3 টি উপায় রয়েছে:
বাশ≥ 4 mapfile
এর সাথে এটি সবচেয়ে দক্ষ ব্যবহার করুন :
mapfile -t my_array < <( my_command )
অন্যথায়, আউটপুট পড়ার একটি লুপ (ধীর, তবে নিরাপদ):
my_array=()
while IFS= read -r line; do
my_array+=( "$line" )
done < <( my_command )
মন্তব্যগুলিতে চার্লস ডাফির পরামর্শ অনুসারে (ধন্যবাদ!), নিম্নলিখিত সংখ্যা 2 এ লুপ পদ্ধতির চেয়ে আরও ভাল অভিনয় করতে পারে:
IFS=$'\n' read -r -d '' -a my_array < <( my_command && printf '\0' )
দয়া করে নিশ্চিত হয়ে নিন যে আপনি ঠিক এই ফর্মটি ব্যবহার করেছেন, অর্থাত্ আপনার নিচেরটি রয়েছে তা নিশ্চিত করুন:
IFS=$'\n'
read
বিবৃতি হিসাবে একই লাইনে : এটি শুধুমাত্র বিবৃতি IFS
জন্যread
পরিবেশ পরিবর্তনশীল সেট করবে । সুতরাং এটি আপনার স্ক্রিপ্টের মোটেও প্রভাব ফেলবে না। এই পরিবর্তনশীলটির উদ্দেশ্যটি read
EOL চরিত্রটিতে স্ট্রিমটি ভাঙ্গতে বলা \n
।
-r
: এটা গুরুত্বপূর্ণ. এটি ব্যাকস্ল্যাশগুলি এস্কেপ সিকোয়েন্স হিসাবে ব্যাখ্যা না করতে বলে read
।
-d ''
: দয়া করে -d
বিকল্প এবং তার যুক্তির মধ্যে স্থানটি নোট করুন ''
। আপনি যদি এখানে কোনও স্থান ছেড়ে না যান ''
তবে কখনই দেখা যাবে না, কারণ এটি যখন বশ বিবৃতিটি বিশ্লেষণ করে তখন উদ্ধৃতি অপসারণের পদক্ষেপে অদৃশ্য হয়ে যাবে । এটি read
নীল বাইটে পড়া বন্ধ করতে বলে । কিছু লোক এটি লিখেন -d $'\0'
তবে এটি সত্যই প্রয়োজন হয় না। -d ''
ভাল.
-a my_array
স্ট্রিমটি পড়ার সময় read
অ্যারে পপুলেট করতে বলে my_array
।
- আপনি ব্যবহার করা আবশ্যক
printf '\0'
বিবৃতি পর my_command
, যাতে read
আয় 0
; এটি না করে আসলে এটি কোনও বড় বিষয় নয় (আপনি কেবলমাত্র একটি রিটার্ন কোড পাবেন 1
, যা আপনি যদি ব্যবহার না করেন তবে ঠিক আছে set -e
- যা আপনার কোনওভাবেই করা উচিত নয়), তবে কেবল এটি মনে রাখবেন। এটি ক্লিনার এবং আরও শব্দার্থগতভাবে সঠিক। মনে রাখবেন যে এটি থেকে আলাদা printf ''
, যা কোনও কিছুই আউটপুট দেয় না। খুশিভাবে সেখানে পড়া বন্ধ করার জন্য printf '\0'
প্রয়োজনীয় একটি নাল বাইট মুদ্রণ করে read
( -d ''
বিকল্পটি মনে রাখবেন ?)।
যদি আপনি এটি করতে পারেন, অর্থাত্, যদি আপনি নিশ্চিত হন যে আপনার কোড বাশো 4 তে চলবে, তবে প্রথম পদ্ধতিটি ব্যবহার করুন। এবং আপনি এটিও খাটো দেখতে পারেন।
আপনি যদি ব্যবহার read
করতে চান তবে লাইনটি পড়ার সাথে সাথে কিছু প্রক্রিয়াজাতকরণ করতে চাইলে লুপের (পদ্ধতি 2) 3 এর চেয়ে বেশি সুবিধা থাকতে পারে: আপনার এতে সরাসরি অ্যাক্সেস রয়েছে ( $line
আমি যে উদাহরণ দিয়েছি তার পরিবর্তনের মাধ্যমে ), এবং আপনার ইতিমধ্যে পঠিত লাইনগুলিতে অ্যাক্সেস রয়েছে ( ${my_array[@]}
আমি যে উদাহরণ দিয়েছি তা দিয়ে অ্যারের মাধ্যমে )।
নোট যা mapfile
প্রতিটি লাইনে পড়ার জন্য কলব্যাককে বিস্তৃত করার একটি উপায় সরবরাহ করে এবং বাস্তবে আপনি প্রতিটি এন লাইনে পড়া কেবল এই কলব্যাকটি কল করতে বলতে পারেন; একটি help mapfile
বিকল্প -C
এবং এর বিকল্পগুলি দেখুন -c
। (এ সম্পর্কে আমার মতামতটি হ'ল এটি কিছুটা জটিল) তবে কখনও কখনও ব্যবহার করা যেতে পারে যদি আপনার কাছে কেবল সহজ জিনিস থাকে - তবে কেন এটি এমনকি প্রথম স্থানে কার্যকর করা হয়েছিল তা আমি সত্যি বুঝতে পারি না!)।
এখন আমি আপনাকে কেন নীচের পদ্ধতিটি বলব:
my_array=( $( my_command) )
স্পেস থাকলে ভাঙা হয়:
$ # I'm using this command to test:
$ echo "one two"; echo "three four"
one two
three four
$ # Now I'm going to use the broken method:
$ my_array=( $( echo "one two"; echo "three four" ) )
$ declare -p my_array
declare -a my_array='([0]="one" [1]="two" [2]="three" [3]="four")'
$ # As you can see, the fields are not the lines
$
$ # Now look at the correct method:
$ mapfile -t my_array < <(echo "one two"; echo "three four")
$ declare -p my_array
declare -a my_array='([0]="one two" [1]="three four")'
$ # Good!
তারপরে কিছু লোক IFS=$'\n'
এটি ঠিক করার জন্য ব্যবহারের পরামর্শ দিবে :
$ IFS=$'\n'
$ my_array=( $(echo "one two"; echo "three four") )
$ declare -p my_array
declare -a my_array='([0]="one two" [1]="three four")'
$ # It works!
তবে এখন গ্লোব সহ আরও একটি কমান্ড ব্যবহার করা যাক :
$ echo "* one two"; echo "[three four]"
* one two
[three four]
$ IFS=$'\n'
$ my_array=( $(echo "* one two"; echo "[three four]") )
$ declare -p my_array
declare -a my_array='([0]="* one two" [1]="t")'
$ # What?
যে কারণ আমি নামক কোনো ফাইল আছে t
বর্তমান ডিরেক্টরির মধ্যে ... এবং এই ফাইলের নাম দ্বারা মেলানো হয় উল্লিখিত glob [three four]
... এই সময়ে কিছু লোক ব্যবহার সুপারিশ করবে set -f
নিষ্ক্রিয় globbing না; কিন্তু এটি তাকান: আপনার পরিবর্তন করতে হবে IFS
এবং ব্যবহার set -f
একটি ফিক্স পাবে ভাঙা কৌশল (এবং আপনি এমনকি এটি ঠিক করে নিচ্ছেন না)! এটি করার সময় আমরা শেলের সাথে লড়াই করছি না , শেলের সাথে কাজ করছি না ।
$ mapfile -t my_array < <( echo "* one two"; echo "[three four]")
$ declare -p my_array
declare -a my_array='([0]="* one two" [1]="[three four]")'
এখানে আমরা শেল নিয়ে কাজ করছি!