ট্র্যাক
/
Bash
Bash
/
সিলেবাস
/
অ্যারে নিয়ে আরও
অ্

অ্যারে নিয়ে আরও মধ্যে Bash

{one: "১টি অনুশীলনী", other: "%{count}টি অনুশীলনী"}

অ্যারে নিয়ে আরও সম্পর্কে

অ্যারে অধ্যায়ে আমরা অ্যারের সাথে পরিচয় করিয়েছিলাম। এই ডকুমেন্টে অ্যারে ব্যবহারের আরও কিছু উপায় দেখানো হবে।

অ্যারের এলিমেন্টগুলোকে একটি স্ট্রিংয়ে জোড়া লাগানো

আগের অ্যারে অধ্যায়ে আপনি "${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"
Advanced
আমরা এটিকে একটি ফাংশনে ঢুকিয়ে রাখতে পারি। বিস্তারিত দেখতে ক্লিক করুন।
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 পরিবর্তন করা হলো বর্তমান শেলে এটি পরিবর্তন এড়ানোর একটি ভালো উপায়। বিস্তারিত দেখতে ক্লিক করুন।
(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")

নেমরেফ অ্যাসোসিয়েটিভ অ্যারে এবং "স্কেলার" ভ্যারিয়েবলের (যেগুলোতে একটি স্ট্রিং মান থাকে) সাথেও কাজ করে।

Note

ফাংশনের ভেতরে declare -p local_array খুব একটা সহায়ক নয়। এটি শুধু declare -n local_array="array_original" দেখাবে। পাস করা অ্যারের নামটি পরীক্ষা করে আপনি অ্যারের বিস্তারিত তথ্য পেতে পারেন: declare -p "$1"

Caution

খেয়াল রাখুন, লোকাল অ্যারের নাম যেন পাস করা অ্যারের নাম থেকে আলাদা হয়। কোডটি তবুও কাজ করবে, কিন্তু এটি এমন "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

আপনার লক্ষ্য যদি "পোর্টেবল" শেল স্ক্রিপ্ট লেখা হয়, তাহলে মানের একটি "লিস্ট" রাখতে আপনি পজিশনাল প্যারামিটারগুলো ব্যবহার করবেন।

GitHub-এর মাধ্যমে সম্পাদনা করুন লিংকটি নতুন একটি উইন্ডো বা ট্যাবে খুলবে