অ্যারে অধ্যায়ে আমরা অ্যারের সাথে পরিচয় করিয়েছিলাম। এই ডকুমেন্টে অ্যারে ব্যবহারের আরও কিছু উপায় দেখানো হবে।
আগের অ্যারে অধ্যায়ে আপনি "${myarray[@]}" দেখেছেন, যেখানে @ ইনডেক্স ব্যবহার করে অ্যারেটিকে আলাদা আলাদা এলিমেন্টে ছড়িয়ে দেওয়া হয়।
তবে কখনও কখনও আপনি সব এলিমেন্টকে একটি স্ট্রিংয়ে জুড়ে দিতে চান।
এজন্য * ইনডেক্স ব্যবহার করুন:
echo "${myarray[*]}"
এই প্রসারণটিকে ডাবল কোটের ভেতরে রাখা আবশ্যক।
Bash বিভাজক অক্ষর হিসেবে IFS বিল্ট-ইন ভ্যারিয়েবলের প্রথম অক্ষরটি ব্যবহার করে।
ডিফল্টভাবে $IFS-এ স্পেস, ট্যাব এবং নিউলাইন থাকে।
myarray=(one two three four)
mystring="${myarray[*]}"
declare -p mystring
# => declare -- mystring="one two three four"
ভিন্ন বিভাজক অক্ষর ব্যবহার করতে আমরা IFS ভ্যারিয়েবলটি বদলে নিতে পারি:
myarray=(one two three four)
IFS=","
mystring="${myarray[*]}"
declare -p mystring
# => declare -- mystring="one,two,three,four"
join() {
local IFS=$1
shift
local elements=("$@")
echo "${elements[*]}"
}
join ":" "${myarray[@]}" # note, the "@" index
# => "one:two:three:four"
ফাংশনের ভেতরে IFS-কে লোকাল করলে আমাদের পুরোনো মানটি সংরক্ষণ করে পরে গ্লোবাল স্কোপে তার আগের মানে ফিরিয়ে দিতে হয় না।
আরও নিখুঁত করতে চাইলে, বিশেষ প্যারামিটার "$*" কোটের ভেতরে রাখলে একই কাজ করে, তাই ফাংশনের আর্গুমেন্টের একটি কপি সংরক্ষণ করার দরকার নেই:
join() {
local IFS=$1
shift
echo "$*"
}
(IFS=","; echo "${myarray[*]}")
বন্ধনীগুলো একটি সাবশেল (বর্তমান শেলের একটি কপি) তৈরি করে। বন্ধনীর ভেতরের কমান্ডগুলো শেষ হলে সাবশেলটি বন্ধ হয়ে যায়, আর পরিবর্তিত IFS ভ্যারিয়েবলটি মুছে যায়।
লক্ষ্য করুন, এটি কাজ করবে না: IFS="," echo "${myarray[*]}"। কারণ প্যারামিটার এক্সপ্যানশন আগে সম্পন্ন হয়, শেল echo কমান্ডে পরিবর্তিত IFS ভ্যারিয়েবল প্রয়োগ করার আগেই।
আপনি হয়তো "${variable:offset:length}" প্যারামিটার এক্সপ্যানশন দেখেছেন, যা ভ্যারিয়েবলের মানের একটি সাবস্ট্রিং-এ প্রসারিত হয়।
অ্যারের একটি স্লাইস বের করতেও আমরা ঠিক একই কাজ করতে পারি।
myarray=(one two three four)
subarray=("${myarray[@]:0:2}")
declare -p subarray
# => declare -a subarray=([0]="one" [1]="two")
subarray=("${myarray[@]:1:3}")
declare -p subarray
# => declare -a subarray=([0]="two" [1]="three" [2]="four")
লেংথের অংশটি বাদ দিলে বোঝায় "অফসেট থেকে অ্যারের শেষ পর্যন্ত":
subarray=("${myarray[@]:2}")
declare -p subarray
# => declare -a subarray=([0]="three" [1]="four")
আপনি হয়তো জানেন এমন অন্য ভাষার মতো এটি ততটা সহজ নয়। একটি ফাংশনে অ্যারে পাঠানোর দুটি প্রধান কৌশল আছে।
প্রথম কৌশলে আপনি অ্যারের সব মান পাঠান, আর ফাংশনের ভেতরে সেগুলো একটি লোকাল অ্যারে তৈরি করে তাতে জমা করেন।
myfunc() {
local array_copy=("$@")
# do stuff with array_copy
declare -p array_copy
}
array_original=(11 22 33 44)
myfunc "${array_original[@]}"
ফাংশনের অ্যারেটি মানগুলোর একটি কপি ধরে রাখে। ফাংশনের ভেতরে অ্যারেতে করা যেকোনো পরিবর্তন বাইরের স্কোপে প্রতিফলিত হয় না।
এই কৌশলটি অন্য ভাষা থেকে আপনি হয়তো জানেন এমন "pass by reference" সুবিধার মতো। আপনি অ্যারের নাম একটি স্ট্রিং হিসেবে পাঠান। ফাংশনটি "nameref" অ্যাট্রিবিউটসহ একটি লোকাল ভ্যারিয়েবল তৈরি করবে। এই লোকাল অ্যারেটি আর গ্লোবাল অ্যারেটি (যার নাম আমরা পাঠিয়েছি) আসলে একই অ্যারে।
myfunc() {
# note the `-n` option
local -n local_array=$1
# do stuff with local_array
for i in "${!local_array[@]}"; do
printf '%d => %s\n' "$i" "${local_array[i]}"
end
# we can mutate it
local_array+=(55 66 77)
}
array_original=(11 22 33 44)
myfunc "array_original"
# show the mutated array
declare -p array_original
# => declare -a array_original=([0]="11" [1]="22" [2]="33" [3]="44" [4]="55" [5]="66" [6]="77")
নেমরেফ অ্যাসোসিয়েটিভ অ্যারে এবং "স্কেলার" ভ্যারিয়েবলের (যেগুলোতে একটি স্ট্রিং মান থাকে) সাথেও কাজ করে।
ফাংশনের ভেতরে declare -p local_array খুব একটা সহায়ক নয়।
এটি শুধু declare -n local_array="array_original" দেখাবে।
পাস করা অ্যারের নামটি পরীক্ষা করে আপনি অ্যারের বিস্তারিত তথ্য পেতে পারেন: declare -p "$1"
খেয়াল রাখুন, লোকাল অ্যারের নাম যেন পাস করা অ্যারের নাম থেকে আলাদা হয়। কোডটি তবুও কাজ করবে, কিন্তু এটি এমন "circular name reference" সতর্কবার্তা দেখাবে:
myfunc() {
local -n a=$1
local IFS=,
echo "${a[*]}"
}
# same name as the function's local variable
a=(one two three)
myfunc a
bash: local: warning: a: circular name reference
bash: warning: a: circular name reference
bash: warning: a: circular name reference
bash: warning: a: circular name reference
one,two,three
যেসব শেল শুধু POSIX স্ট্যান্ডার্ড মেনে চলার চেষ্টা করে (যেমন ash ও dash), সেগুলোতে কোনো অ্যারে নেই।
সবচেয়ে কাছাকাছি যা করা যায় তা হলো পজিশনাল প্যারামিটার ব্যবহার করা।
$1, $2 ইত্যাদি।"$@" দিয়ে সেগুলোকে আলাদা আলাদা এলিমেন্টে ছড়িয়ে দেওয়া হয়"$*" দিয়ে সেগুলোকে একটি স্ট্রিংয়ে জোড়া লাগানো হয়$#
সেগুলোতে মান অ্যাসাইন করতে set কমান্ডটি ব্যবহার করুন:
set -- one two three
set -- "$@" four
for item in "$@"; do
echo "do something with $item"
done
আপনার লক্ষ্য যদি "পোর্টেবল" শেল স্ক্রিপ্ট লেখা হয়, তাহলে মানের একটি "লিস্ট" রাখতে আপনি পজিশনাল প্যারামিটারগুলো ব্যবহার করবেন।