ব্যাশ একটি শক্তিশালী প্রোগ্রামিং ভাষা, যা কমান্ড লাইনে এবং শেল স্ক্রিপ্টে ব্যবহারের জন্য পুরোপুরি ডিজাইন করা হয়েছে। আমার তিন-ভলিউমের লিনাক্স স্ব-অধ্যয়ন কোর্সের উপর ভিত্তি করে এই তিন-খণ্ডের সিরিজ, কমান্ড-লাইন ইন্টারফেসে (CLI) প্রোগ্রামিং ভাষা হিসাবে ব্যাশ ব্যবহার করে।
এই সিরিজের প্রথম নিবন্ধটি ব্যাশের সাথে কিছু সাধারণ কমান্ড-লাইন প্রোগ্রামিং অন্বেষণ করেছে, যার মধ্যে ভেরিয়েবল এবং কন্ট্রোল অপারেটর ব্যবহার করা রয়েছে। দ্বিতীয় নিবন্ধটি ফাইলের ধরন, স্ট্রিং, সংখ্যাসূচক এবং বিবিধ লজিক্যাল অপারেটরগুলিকে দেখেছে যা এক্সিকিউশন-ফ্লো কন্ট্রোল লজিক এবং ব্যাশে বিভিন্ন ধরণের শেল সম্প্রসারণ প্রদান করে। এই তৃতীয় (এবং চূড়ান্ত) নিবন্ধটি বিভিন্ন ধরণের পুনরাবৃত্তিমূলক ক্রিয়াকলাপ সম্পাদনের জন্য লুপগুলির ব্যবহার এবং সেই লুপগুলিকে নিয়ন্ত্রণ করার উপায়গুলি পরীক্ষা করে৷
লুপ
আমি কখনও ব্যবহার করেছি এমন প্রতিটি প্রোগ্রামিং ল্যাঙ্গুয়েজে অন্তত কয়েক ধরনের লুপ স্ট্রাকচার রয়েছে যা পুনরাবৃত্তিমূলক ক্রিয়াকলাপ সম্পাদন করার জন্য বিভিন্ন ক্ষমতা প্রদান করে। আমি প্রায়শই জন্য লুপ ব্যবহার করি কিন্তু আমিও সময় এবং যতক্ষণ পর্যন্ত লুপগুলি দরকারী খুঁজে পাই৷
লুপের জন্য
ব্যাশের এর জন্য বাস্তবায়ন কমান্ড, আমার মতে, বেশিরভাগের চেয়ে একটু বেশি নমনীয় কারণ এটি অ-সংখ্যাসূচক মানগুলি পরিচালনা করতে পারে; বিপরীতে, উদাহরণস্বরূপ, স্ট্যান্ডার্ড সি ভাষা এর জন্য লুপ শুধুমাত্র সাংখ্যিক মান নিয়ে কাজ করতে পারে।
এর জন্য ব্যাশ সংস্করণের মৌলিক কাঠামো কমান্ড সহজ:
তালিকা 1-তে Var-এর জন্যfor Var in list1 ; do list2 ; done
এটি এতে অনুবাদ করে: "তালিকা1-এর প্রতিটি মানের জন্য, $Var সেট করুন সেই মানটিতে এবং তারপর সেই মানটি ব্যবহার করে list2 তে প্রোগ্রাম স্টেটমেন্টগুলি সম্পাদন করুন; যখন তালিকা1-এর সমস্ত মান ব্যবহার করা হয়, তখন এটি সমাপ্ত হয়, তাই লুপ থেকে প্রস্থান করুন।" তালিকা 1-এর মানগুলি মানগুলির একটি সাধারণ, সুস্পষ্ট স্ট্রিং হতে পারে বা সেগুলি একটি কমান্ড প্রতিস্থাপনের ফলাফল হতে পারে (দ্বিতীয়তে বর্ণিত সিরিজের নিবন্ধ)। আমি প্রায়শই এই নির্মাণ ব্যবহার করি।
এটি চেষ্টা করতে, নিশ্চিত করুন যে ~/testdir এখনও বর্তমান ওয়ার্কিং ডিরেক্টরি (PWD)। ডিরেক্টরিটি পরিষ্কার করুন, তারপর এর জন্য একটি তুচ্ছ উদাহরণ দেখুন৷ মানের একটি সুস্পষ্ট তালিকা দিয়ে শুরু লুপ। এই তালিকাটি আলফানিউমেরিক মানের মিশ্রণ—কিন্তু ভুলে যাবেন না যে সমস্ত ভেরিয়েবলই স্ট্রিং এবং সেগুলিকে সেভাবে বিবেচনা করা যেতে পারে৷
[student@studentvm1 testdir]$ rm *
[student@studentvm1 testdir]$ for I in a b c d 1 2 3 4 ; do echo $I ; done
a
b
c
d
1
2
3
4
এখানে আরও অর্থপূর্ণ পরিবর্তনশীল নামের সাথে একটু বেশি দরকারী সংস্করণ রয়েছে:
[student@studentvm1 testdir]$ for Dept in "Human Resources" Sales Finance "Information Technology" Engineering Administration Research ; do echo "Department $Dept" ; done
Department Human Resources
Department Sales
Department Finance
Department Information Technology
Department Engineering
Department Administration
Department Research
কিছু ডিরেক্টরি তৈরি করুন (এবং এটি করার সময় কিছু অগ্রগতি তথ্য দেখান):
[student@studentvm1 testdir]$ for Dept in "Human Resources" Sales Finance "Information Technology" Engineering Administration Research ; do echo "Working on Department $Dept" ; mkdir "$Dept" ; done
Working on Department Human Resources
Working on Department Sales
Working on Department Finance
Working on Department Information Technology
Working on Department Engineering
Working on Department Administration
Working on Department Research
[student@studentvm1 testdir]$ ll
total 28
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Administration
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Engineering
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Finance
drwxrwxr-x 2 student student 4096 Apr 8 15:45 'Human Resources'
drwxrwxr-x 2 student student 4096 Apr 8 15:45 'Information Technology'
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Research
drwxrwxr-x 2 student student 4096 Apr 8 15:45 Sales
$Dept ভেরিয়েবলকে অবশ্যই mkdir-এ উদ্ধৃতি দিয়ে আবদ্ধ করতে হবে বিবৃতি; অন্যথায়, দুই-অংশের বিভাগের নাম (যেমন "তথ্য প্রযুক্তি") দুটি পৃথক বিভাগ হিসাবে বিবেচিত হবে। এটি একটি সর্বোত্তম অনুশীলনকে হাইলাইট করে যা আমি অনুসরণ করতে চাই:সমস্ত ফাইল এবং ডিরেক্টরির নাম একটি একক শব্দ হওয়া উচিত। যদিও বেশিরভাগ আধুনিক অপারেটিং সিস্টেম নামের স্পেসগুলি মোকাবেলা করতে পারে, তবে স্ক্রিপ্ট এবং সিএলআই প্রোগ্রামগুলিতে সেই বিশেষ কেসগুলি বিবেচনা করা হয় তা নিশ্চিত করতে সিসাডমিনদের জন্য অতিরিক্ত কাজ লাগে। (এগুলি প্রায় অবশ্যই বিবেচনা করা উচিত, এমনকি যদি তারা বিরক্তিকর হয় কারণ আপনি কখনই জানেন না যে আপনার কাছে কী ফাইল থাকবে৷)
সুতরাং, ~/testdir-এ সবকিছু মুছে দিন —আবার—এবং এটি আরও একবার করুন:
[student@studentvm1 testdir]$ rm -rf * ; ll
total 0
[student@studentvm1 testdir]$ for Dept in Human-Resources Sales Finance Information-Technology Engineering Administration Research ; do echo "Working on Department $Dept" ; mkdir "$Dept" ; done
Working on Department Human-Resources
Working on Department Sales
Working on Department Finance
Working on Department Information-Technology
Working on Department Engineering
Working on Department Administration
Working on Department Research
[student@studentvm1 testdir]$ ll
total 28
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Administration
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Engineering
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Finance
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Human-Resources
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Information-Technology
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Research
drwxrwxr-x 2 student student 4096 Apr 8 15:52 Sales
ধরুন কেউ একটি নির্দিষ্ট লিনাক্স কম্পিউটারে সমস্ত RPMগুলির একটি তালিকা এবং প্রতিটির একটি সংক্ষিপ্ত বিবরণ চেয়েছে। আমি যখন উত্তর ক্যারোলিনা রাজ্যের জন্য কাজ করি তখন আমার সাথে এটি ঘটেছিল। যেহেতু ওপেন সোর্স সেই সময়ে রাষ্ট্রীয় সংস্থাগুলির দ্বারা ব্যবহারের জন্য "অনুমোদিত" ছিল না, এবং আমি শুধুমাত্র আমার ডেস্কটপ কম্পিউটারে লিনাক্স ব্যবহার করতাম, তাই আমার কম্পিউটারে ইনস্টল করা সফ্টওয়্যারের প্রতিটি অংশের একটি তালিকা প্রয়োজন যে তারা একটি ব্যতিক্রম "অনুমোদন" করতে পারে।
কিভাবে আপনি যে যোগাযোগ করবে? rpm –qa জ্ঞান দিয়ে শুরু করার জন্য এখানে একটি উপায় কমান্ড একটি RPM এর একটি সম্পূর্ণ বিবরণ প্রদান করে, যার মধ্যে দুটি আইটেম যা PHB চায়:সফ্টওয়্যার নাম এবং একটি সংক্ষিপ্ত সারাংশ।
এক সময়ে চূড়ান্ত ফলাফল পর্যন্ত তৈরি করুন। প্রথমে, সমস্ত RPM তালিকা করুন:
[student@studentvm1 testdir]$ rpm -qa
perl-HTTP-Message-6.18-3.fc29.noarch
perl-IO-1.39-427.fc29.x86_64
perl-Math-Complex-1.59-429.fc29.noarch
lua-5.3.5-2.fc29.x86_64
java-11-openjdk-headless-11.0.ea.28-2.fc29.x86_64
util-linux-2.32.1-1.fc29.x86_64
libreport-fedora-2.9.7-1.fc29.x86_64
rpcbind-1.2.5-0.fc29.x86_64
libsss_sudo-2.0.0-5.fc29.x86_64
libfontenc-1.1.3-9.fc29.x86_64
<snip>
বাছাই যোগ করুন এবং uniq তালিকা বাছাই এবং অনন্যগুলি মুদ্রণ করার জন্য কমান্ড (যেহেতু অভিন্ন নাম সহ কিছু RPM ইনস্টল করা সম্ভব):
[student@studentvm1 testdir]$ rpm -qa | sort | uniq
a2ps-4.14-39.fc29.x86_64
aajohan-comfortaa-fonts-3.001-3.fc29.noarch
abattis-cantarell-fonts-0.111-1.fc29.noarch
abiword-3.0.2-13.fc29.x86_64
abrt-2.11.0-1.fc29.x86_64
abrt-addon-ccpp-2.11.0-1.fc29.x86_64
abrt-addon-coredump-helper-2.11.0-1.fc29.x86_64
abrt-addon-kerneloops-2.11.0-1.fc29.x86_64
abrt-addon-pstoreoops-2.11.0-1.fc29.x86_64
abrt-addon-vmcore-2.11.0-1.fc29.x86_64
<snip>
যেহেতু এটি RPMগুলির সঠিক তালিকা দেয় যা আপনি দেখতে চান, আপনি এটিকে একটি লুপে ইনপুট তালিকা হিসাবে ব্যবহার করতে পারেন যা প্রতিটি RPM-এর সমস্ত বিবরণ প্রিন্ট করবে:
[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done
এই কোডটি আপনার চেয়ে বেশি ডেটা তৈরি করে। লক্ষ্য করুন যে লুপ সম্পূর্ণ হয়েছে। পরবর্তী পদক্ষেপ হল শুধুমাত্র PHB দের অনুরোধ করা তথ্য বের করা। সুতরাং, একটি egrep যোগ করুন কমান্ড, যা ^Name নির্বাচন করতে ব্যবহৃত হয় অথবা ^সারাংশ . ক্যারেট (^ ) লাইনের শুরু নির্দিষ্ট করে; এইভাবে, লাইনের শুরুতে নাম বা সারাংশ সহ যেকোনো লাইন প্রদর্শিত হয়।
[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done | egrep -i "^Name|^Summary"
Name : a2ps
Summary : Converts text and other types of files to PostScript
Name : aajohan-comfortaa-fonts
Summary : Modern style true type font
Name : abattis-cantarell-fonts
Summary : Humanist sans serif font
Name : abiword
Summary : Word processing program
Name : abrt
Summary : Automatic bug detection and reporting tool
<snip>
আপনি grep চেষ্টা করতে পারেন egrep এর পরিবর্তে উপরের কমান্ডে, কিন্তু এটি কাজ করবে না। আপনি কম এর মাধ্যমে এই কমান্ডের আউটপুট পাইপ করতে পারেন ফলাফল অন্বেষণ করতে ফিল্টার. চূড়ান্ত কমান্ড ক্রম এই মত দেখায়:
[student@studentvm1 testdir]$ for RPM in `rpm -qa | sort | uniq` ; do rpm -qi $RPM ; done | egrep -i "^Name|^Summary" > RPM-summary.txt
এই কমান্ড-লাইন প্রোগ্রাম পাইপলাইন, পুনঃনির্দেশ, এবং একটি এর জন্য ব্যবহার করে লুপ—সব এক লাইনে। এটি আপনার ছোট CLI প্রোগ্রামের আউটপুটকে একটি ফাইলে পুনঃনির্দেশ করে যা একটি ইমেলে বা অন্যান্য উদ্দেশ্যে ইনপুট হিসাবে ব্যবহার করা যেতে পারে৷
এক সময়ে এক ধাপে প্রোগ্রাম তৈরি করার এই প্রক্রিয়াটি আপনাকে প্রতিটি ধাপের ফলাফল দেখতে দেয় এবং নিশ্চিত করে যে এটি আপনার প্রত্যাশা অনুযায়ী কাজ করছে এবং কাঙ্খিত ফলাফল প্রদান করে।
এই অনুশীলন থেকে, PHBগুলি 1,900 টির বেশি পৃথক RPM প্যাকেজের একটি তালিকা পেয়েছে। আমি গুরুতরভাবে সন্দেহ যে কেউ এই তালিকা পড়ে. কিন্তু তারা যা চেয়েছিল তা আমি তাদের দিয়েছি, এবং আমি তাদের কাছ থেকে এ সম্পর্কে আর কোনো শব্দ শুনিনি।
অন্যান্য লুপ
ব্যাশে আরও দুই ধরনের লুপ স্ট্রাকচার পাওয়া যায়:যখন এবং যতক্ষণ কাঠামো, যা সিনট্যাক্স এবং ফাংশন উভয় ক্ষেত্রেই একে অপরের সাথে খুব মিল। এই লুপ স্ট্রাকচারের মৌলিক সিনট্যাক্স সহজ:
while [ expression ] ; do list ; done
এবং
until [ expression ] ; do list ; done
প্রথমটির যুক্তি হল:"অভিব্যক্তিটি সত্য হিসাবে মূল্যায়ন করার সময়, প্রোগ্রামের বিবৃতিগুলির তালিকাটি কার্যকর করুন। যখন অভিব্যক্তিটি মিথ্যা হিসাবে মূল্যায়ন করে, তখন লুপ থেকে প্রস্থান করুন।" এবং দ্বিতীয়টি:"অভিব্যক্তিটি সত্য হিসাবে মূল্যায়ন না হওয়া পর্যন্ত, প্রোগ্রামের বিবৃতিগুলির তালিকা চালান৷ যখন অভিব্যক্তিটি সত্য হিসাবে মূল্যায়ন হয়, তখন লুপ থেকে প্রস্থান করুন৷"
While loop
৷যখন লুপ প্রোগ্রাম স্টেটমেন্টের একটি সিরিজ চালানোর জন্য ব্যবহার করা হয় যখন (যতদিন) লজিক্যাল এক্সপ্রেশনটি সত্য হিসাবে মূল্যায়ন করা হয়। আপনার PWD এখনও ~/testdir হওয়া উচিত .
যখন এর সহজতম রূপ লুপ এমন একটি যা চিরকাল চলে। নিম্নলিখিত ফর্মটি সর্বদা একটি "সত্য" রিটার্ন কোড তৈরি করতে সত্য বিবৃতি ব্যবহার করে। আপনি একটি সাধারণ "1" ব্যবহার করতে পারেন—এবং এটি ঠিক একই কাজ করবে—কিন্তু এটি সত্য বিবৃতিটির ব্যবহারকে চিত্রিত করে:
[student@studentvm1 testdir]$ X=0 ; while [ true ] ; do echo $X ; X=$((X+1)) ; done | head
0
1
2
3
4
5
6
7
8
9
[student@studentvm1 testdir]$
এই CLI প্রোগ্রামটি এখন আরও অর্থপূর্ণ হওয়া উচিত যে আপনি এর অংশগুলি অধ্যয়ন করেছেন। প্রথমে, এটি $X সেট করে পূর্ববর্তী প্রোগ্রাম বা CLI কমান্ড থেকে একটি মান অবশিষ্ট থাকলে শূন্যে। তারপর, যেহেতু লজিক্যাল এক্সপ্রেশন [ true ] সর্বদা 1 তে মূল্যায়ন করে, যা সত্য, করুন এর মধ্যে প্রোগ্রাম নির্দেশাবলীর তালিকা এবং হয়েছে চিরতরে কার্যকর করা হয়—অথবা যতক্ষণ না আপনি Ctrl+C টিপেন অথবা অন্যথায় প্রোগ্রামে একটি সংকেত 2 পাঠান। এই নির্দেশাবলী হল একটি গাণিতিক সম্প্রসারণ যা $X এর বর্তমান মান প্রিন্ট করে এবং তারপর একে একে বৃদ্ধি করে।
সিসাডমিনের জন্য লিনাক্স দর্শনের একটি নীতি কমনীয়তার জন্য প্রচেষ্টা করা, এবং কমনীয়তা অর্জনের একটি উপায় সরলতা। আপনি পরিবর্তনশীল ইনক্রিমেন্ট অপারেটর ব্যবহার করে এই প্রোগ্রামটিকে সহজ করতে পারেন, ++ . প্রথম উদাহরণে, ভেরিয়েবলের বর্তমান মান প্রিন্ট করা হয়, এবং তারপর পরিবর্তনশীলটি বৃদ্ধি করা হয়। এটি ++ বসিয়ে নির্দেশিত হয় চলকের পরে অপারেটর:
[student@studentvm1 ~]$ X=0 ; while [ true ] ; do echo $((X++)) ; done | head
0
1
2
3
4
5
6
7
8
9
এখন | মুছুন মাথা প্রোগ্রামের শেষ থেকে আবার চালান।
এই সংস্করণে, ভেরিয়েবলের মান প্রিন্ট করার আগে বৃদ্ধি করা হয়। এটি ++ স্থাপন করে নির্দিষ্ট করা হয়েছে ভেরিয়েবলের আগে অপারেটর। আপনি পার্থক্য দেখতে পারেন?
[student@studentvm1 ~]$ X=0 ; while [ true ] ; do echo $((++X)) ; done | head
1
2
3
4
5
6
7
8
9
আপনি দুটি বিবৃতিকে একটি এককভাবে কমিয়েছেন যা ভেরিয়েবলের মান প্রিন্ট করে এবং মান বৃদ্ধি করে। এছাড়াও একটি হ্রাস অপারেটর আছে, --- .
একটি নির্দিষ্ট সংখ্যায় লুপ বন্ধ করার জন্য আপনার একটি পদ্ধতি প্রয়োজন। এটি সম্পন্ন করতে, সত্যিকারের সাংখ্যিক মূল্যায়ন অভিব্যক্তিতে প্রকৃত অভিব্যক্তি পরিবর্তন করুন। প্রোগ্রামটি 5 এ লুপ করুন এবং বন্ধ করুন। নীচের উদাহরণ কোডে, আপনি দেখতে পারেন যে -le "এর চেয়ে কম বা সমান" এর জন্য যৌক্তিক সংখ্যাসূচক অপারেটর। এর অর্থ হল:"যতদিন $X 5 এর থেকে কম বা সমান, লুপ চলতে থাকবে। যখন $X 6 এ বৃদ্ধি পেলে, লুপটি বন্ধ হয়ে যায়।"
[student@studentvm1 ~]$ X=0 ; while [ $X -le 5 ] ; do echo $((X++)) ; done
0
1
2
3
4
5
[student@studentvm1 ~]$
লুপ না হওয়া পর্যন্ত
যতক্ষণ কমান্ড অনেকটা while এর মত আদেশ পার্থক্য হল যে লজিক্যাল এক্সপ্রেশন "সত্য" হিসাবে মূল্যায়ন না হওয়া পর্যন্ত এটি লুপ চলতে থাকবে। এই নির্মাণের সহজতম রূপটি দেখুন:
[student@studentvm1 ~]$ X=0 ; until false ; do echo $((X++)) ; done | head
0
1
2
3
4
5
6
7
8
9
[student@studentvm1 ~]$
এটি একটি নির্দিষ্ট মান গণনা করার জন্য একটি যৌক্তিক তুলনা ব্যবহার করে:
[student@studentvm1 ~]$ X=0 ; until [ $X -eq 5 ] ; do echo $((X++)) ; done
0
1
2
3
4
[student@studentvm1 ~]$ X=0 ; until [ $X -eq 5 ] ; do echo $((++X)) ; done
1
2
3
4
5
[student@studentvm1 ~]$
সারাংশ
এই সিরিজটি Bash কমান্ড-লাইন প্রোগ্রাম এবং শেল স্ক্রিপ্ট তৈরির জন্য অনেক শক্তিশালী টুলস অনুসন্ধান করেছে। কিন্তু এটি ব্যাশের সাথে আপনি করতে পারেন এমন অনেক আকর্ষণীয় জিনিসের উপর পৃষ্ঠটি খুব কমই স্ক্র্যাচ করেছে; বাকিটা আপনার উপর।
আমি আবিষ্কার করেছি যে ব্যাশ প্রোগ্রামিং শেখার সর্বোত্তম উপায় হল এটি করা। একটি সাধারণ প্রকল্প খুঁজুন যার জন্য একাধিক ব্যাশ কমান্ড প্রয়োজন এবং সেগুলির মধ্যে একটি CLI প্রোগ্রাম তৈরি করুন। সিসাডমিনরা অনেক কাজ করে যা নিজেদেরকে CLI প্রোগ্রামিং-এ ধার দেয়, তাই আমি নিশ্চিত যে আপনি সহজেই স্বয়ংক্রিয়ভাবে কাজ খুঁজে পাবেন।
অনেক বছর আগে, অন্যান্য শেল ভাষা এবং পার্লের সাথে পরিচিত হওয়া সত্ত্বেও, আমি আমার সমস্ত সিসাডমিন অটোমেশন কাজের জন্য ব্যাশ ব্যবহার করার সিদ্ধান্ত নিয়েছিলাম। আমি আবিস্কার করেছি যে-কখনও কখনও একটু খোঁজাখুঁজি করেই-আমি আমার প্রয়োজনীয় সবকিছু সম্পন্ন করতে ব্যাশ ব্যবহার করতে পেরেছি।