ট্র্যাক
/
Bash
Bash
/
সিলেবাস
/
পাইপলাইন ও কমান্ড লিস্ট
পা

পাইপলাইন ও কমান্ড লিস্ট মধ্যে Bash

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

পাইপলাইন ও কমান্ড লিস্ট সম্পর্কে

আমরা দেখেছি কীভাবে সাধারণ কমান্ড লিখতে হয়, যেখানে একটি কমান্ডের পরে আর্গুমেন্ট থাকে। এখন দেখব কীভাবে সাধারণ কমান্ড জুড়ে দিয়ে আরও জটিল কমান্ড তৈরি করা যায়।

ইনপুট ও আউটপুট

শুরু করার আগে ইনপুট/আউটপুট নিয়ে একটু পরিচিতি জেনে নিই।

প্রসেসগুলোর "স্ট্যান্ডার্ড I/O চ্যানেল" থাকে।

  • একটি প্রসেস "stdin"-এ ইনপুট নিতে পারে।
  • একটি প্রসেস "stdout"-এ আউটপুট দিতে পারে।
  • একটি প্রসেস "stderr"-এ এরর আউটপুট দিতে পারে।

tr কমান্ডটি এর একটি খুব খাঁটি উদাহরণ। এটি কেবল তার ইনপুট থেকে টেক্সট পড়ে, ক্যারেক্টার ট্রান্সলিটারেশন করে, আর ফলাফল টেক্সট তার আউটপুটে প্রিন্ট করে।

"stdio" চ্যানেল নিয়ে কাজ করার বিষয়ে সিলেবাসে পরে আরও দেখব।

পাইপলাইন

এটি শেল প্রোগ্রামিংয়ের অন্যতম প্রধান আকর্ষণ। পাইপলাইন দিয়ে টেক্সটের একটি স্ট্রিমে জটিল রূপান্তর তৈরি করা যায়।

ব্যবহারকারীদের একটি সাজানো তালিকা তৈরি করতে:

cat /etc/passwd | cut -d : -f 1 | sort

পাইপ চিহ্নটি (|) একটি কমান্ডের আউটপুটকে আরেকটি কমান্ডের ইনপুটের সঙ্গে যুক্ত করে। cut পড়ে cat-এর আউটপুট, আর sort পড়ে cut-এর আউটপুট।

Advanced
  • ডিফল্টভাবে, পাইপলাইনের প্রতিটি কমান্ড আলাদা একটি সাবশেলে রান করে। (সাবশেল হলো একটি চাইল্ড প্রসেস, যা চলমান শেলের একটি কপি।)

  • পাইপলাইন রান করার একটি পারফরম্যান্স খরচ আছে। আপনার যদি একই ধরনের কমান্ডের লম্বা পাইপলাইন জমে যায়, তাহলে সেগুলোকে একটি কমান্ডে মিলিয়ে দেওয়ার কথা ভাবুন। উদাহরণস্বরূপ, grep, cut, sed, awk আর tr-এর একাধিক ইনস্ট্যান্স ব্যবহার করা পাইপলাইন সাধারণত দক্ষতার জন্য একটি awk কমান্ডে মিলিয়ে ফেলা যায়।

  • একটি পাইপলাইনের এক্সিট স্ট্যাটাস হলো পাইপলাইনের শেষ কমান্ডের এক্সিট স্ট্যাটাস। এর মানে, আগের কোনো কমান্ড ব্যর্থ হলেও শেষ কমান্ড সফল হলে পুরো পাইপলাইনের এক্সিট স্ট্যাটাস শূন্য হয়।

    এটি বদলে দিতে পারে এমন একটি শেল সেটিং আছে; যদি "pipefail" সেটিং চালু করা থাকে (set -o pipefail দিয়ে), তাহলে পাইপলাইনের এক্সিট স্ট্যাটাস হবে:

    • সব কমান্ড সফল হলে শূন্য, নাহলে
    • পাইপলাইনের কমান্ডগুলোর শেষ অ-শূন্য এক্সিট স্ট্যাটাস।

কমান্ড লিস্ট

কমান্ড লিস্ট হলো ; (বা নিউলাইন), && বা || দিয়ে আলাদা করা পাইপলাইনগুলোর একটি ক্রম।

  • A; B হলো এমন একটি কমান্ড লিস্ট, যেখানে A শেষ হওয়ার পরে B চলে।
  • A && B, যেখানে B চলে শুধু তখনই, যখন A সফল হয় (শূন্য স্ট্যাটাস নিয়ে এক্সিট করে)।
  • A || B, যেখানে B চলে শুধু তখনই, যখন A ব্যর্থ হয় (অ-শূন্য স্ট্যাটাস নিয়ে এক্সিট করে)।

একটি কমান্ড লিস্টের এক্সিট স্ট্যাটাস হলো সর্বশেষ যে কমান্ডটি চালানো হয়েছিল তার এক্সিট স্ট্যাটাস।

&& ও || অপারেটরগুলোকে শিকলে সাজানো যায়, যাতে পরের কমান্ডটি আগের কমান্ডগুলোর স্ট্যাটাসের ভিত্তিতে শর্তসাপেক্ষে চলে। উদাহরণস্বরূপ

A && B && C && D || E
  • A সফল হলে B চলে,
  • A আর B সফল হলে C চলে,
  • A, B আর C সফল হলে D চলে,
  • A, B, C বা D-এর যেকোনো একটি ব্যর্থ হলে E চলে।
Caution

এই লজিক অপারেটরগুলো অল্পই ব্যবহার করুন। এগুলো দ্রুত পড়ার অযোগ্য কোড, বা বোঝা কঠিন এমন লজিক তৈরি করতে পারে।

উদাহরণস্বরূপ, আপনার মনে হতে পারে এগুলো একই:

if A; then B; else C; fi
A && B || C

পার্থক্যটা হলো: C কখন চলে?

  • প্রথম অংশে (if স্টেটমেন্টে), C চলে শুধু A ব্যর্থ হলে।
  • দ্বিতীয় অংশে, C চলে যদি A ব্যর্থ হয় বা A সফল হয় কিন্তু B ব্যর্থ হয়!

কমান্ড লিস্টের ব্যবহার

এখানে কয়েকটি উদাহরণ, যেখানে কমান্ড লিস্ট কোডকে সহজ করতে পারে।

একটি ফাইল থেকে লাইনের ব্লক পড়া

ধরুন, আপনার কাছে ত্রিভুজের ডেটা আছে এমন একটি ডেটা ফাইল আছে, আর একটি ত্রিভুজকে প্রকাশ করা হয় তার বাহুগুলো ধারণ করা তিনটি আলাদা লাইন দিয়ে।

$ cat triangle.dat
3
4
5
9
12
14

আপনি একটি while লুপ ব্যবহার করতে পারেন, যেখানে শর্তটি হলো তিনটি আলাদা read কমান্ড:

while read a && read b && read c; do
    if is_pythagorean "$a" "$b" "$c"; then
        echo "$a:$b:$c is pythagorean"
    else
        echo "$a:$b:$c is not pythagorean"
    fi
done < triangle.dat

ধরে নিলাম is_pythagorean এমন একটি কমান্ড, যা নির্ণয় করে তিনটি বাহু পিথাগোরীয় সমীকরণ মেনে চলে কি না, তাহলে আউটপুট হবে:

3:4:5 is pythagorean
9:12:14 is not pythagorean
অ্যাসার্শন

অনেক প্রোগ্রামিং ভাষায় এক ধরনের অ্যাসার্শন থাকে, যেখানে কোনো শর্ত ব্যর্থ হলে একটি এক্সেপশন ছোড়া হয়

assert(user == "Administrator", "wrong user");

Bash-এ একটি OR অপারেটর দিয়ে সেই কাজটি করা যায়:

die () { # a little convenience function
    echo "$*" >&2
    exit 1
}

[[ $user == "Administrator" ]] || die "wrong user"
[[ $password == "secret!" ]]   || die "incorrect password"

স্টাইল সংক্রান্ত বিষয়

লম্বা কমান্ড লিস্ট খুব দ্রুতই পড়া কঠিন হয়ে পড়ে। নিউলাইন বেশি করে ব্যবহার করলে অনেক সুবিধা হয়।

এই উদাহরণটি দেখুন, যেখানে দুটি শর্ত পূরণ হলে একটি শব্দ অ্যারেতে যোগ করা হয়।

[[ "$word" != "$topic" ]] && [[ "$key" == "$(sorted "$topic")" ]] && anagrams+=("$candidate")

Bash-এ পাইপ বা লজিক অপারেটরের পরে একটি নিউলাইন যোগ করা যায়।

[[ "$word" != "$topic" ]] &&
[[ "$key" == "$(sorted "$topic")" ]] &&
anagrams+=("$candidate")

তবে লাইনের শেষে অপারেটরটি সহজে চোখ এড়িয়ে যেতে পারে। লাইন কন্টিনিউয়েশন ব্যবহার করলে আপনি অপারেটরটি প্রথমে বসাতে পারেন, যা থেকে স্পষ্ট বোঝা যায় যে লিস্টটি তখনও চলছে:

[[ "$word" != "$topic" ]] \
&& [[ "$key" == "$(sorted "$topic")" ]] \
&& anagrams+=("$candidate")
Note

লাইন কন্টিনিউয়েশন হলো "ব্যাকস্ল্যাশ" আর "নিউলাইন" এই দুই অক্ষরের ক্রম (\ + \n)। Bash যখন এই ক্রমটি দেখে, তখন এটি কোড থেকে কেবল মুছে যায়, আর এভাবেই পরের লাইন দিয়ে বর্তমান লাইনটি চলতে থাকে। খেয়াল রাখবেন, ব্যাকস্ল্যাশ আর নিউলাইনের মাঝে যেন কোনো স্পেস না থাকে।

আরেকটি উদাহরণ দেখুন

printf "%s\n" "${numbers[@]}" | bc --mathlib | sort --general-numeric-sort

অথবা

printf "%s\n" "${numbers[@]}" \
| bc --mathlib \
| sort --general-numeric-sort
GitHub-এর মাধ্যমে সম্পাদনা করুন লিংকটি নতুন একটি উইন্ডো বা ট্যাবে খুলবে