دستورات شرطی در تمامی زبانهای برنامهنویسی وجود دارند و اسکریپتنویسی Shell هم از این قاعده مستثنی نیست؛ زمانی که از یک دستور شرطی در اسکریپت خود استفاده میکنیم، فرایند بعدی بستگی به نتیجهٔ یکی از شرایط زیر دارد:
- مقایسهٔ ۲ عدد یا استرینگ با یکدیگر
- مقدار بازگشتی یک دستور (همانطور که قبلاً اشاره شد، عدد ۰ نشاندهندهٔ موفقیتآمیز بودن کامند است و سایر اعداد هم حاکی از عدم موفقیت یک کامندند).
- چک کردن وجود یک فایل یا پرمیشن (مجوز) و چیزهایی از این دست
نکته |
بهطورکلی، منظور از String (استرینگ یا رشته) مجموعهای از علائم، کاراکترها، اعداد و یا هرچیزی است؛ بهطور مثال، عبارت BEHZADMORADI1362 یک استرینگ است. |
بهطور خلاصه، فرم یک دستور شرطی صحیح به شکل زیر است:
if TEST-COMMANDS; then CONSEQUENT-COMMANDS; fi
اگر بخواهیم دستورات فوق را بهصورت خواناتر مشاهده کنیم، میتوانیم آنرا بهصورت زیر بازنویسی کنیم:
if condition
then
statements
else
statements
fi
بهعنوان مثال، دستور if زیر چک میکند ببیند که آیا فایلی تحتعنوان etc/passwd/ روی سیستم وجود دارد یا خیر و درصورتیکه فایل یافت شد، پیامی حاوی .etc/passwd exists/ نمایش داده میشود:
if [ -f /etc/passwd ]
then
echo "/etc/passwd exists."
fi
در اسکریپت فوق، به نحوهٔ استفاده از [ ] خوب توجه کنید؛ بهعبارت دیگر، شرطی که قرار است تست کنیم را داخل علائم [ ] قرار میدهیم. بهعنوان یک مثال جامعتر از دستورات شرطی در Shell لینوکس، فایلی میسازیم تحتعنوان ifscript.sh و اسکریپتهای زیر را داخل آن مینویسیم:
#! /bin/bash
file=$1
if [ -f $file]
then
echo -e "The $file exists"
else
echo -e "The $file does not exist"
fi
در تفسیر اسکریپت فوق بایستی گفت همانطور که قبلاً گفته شد، در خط اول مسیر مفسر بش را دادهایم که قرار است این اسکریپت را اجرا کند؛ در خط دوم پارامتر ورودی که از طریق کامندلاین ارسال میشود در متغیری تحتعنوان file ذخیره میشود و سپس در خط سوم چک میشود که آیا چنین فایلی روی سیستم وجود دارد یا خیر؛ اگر فایل وجود داشت دستور مقابل اولین echo چاپ میشود و اگر هم وجود نداشت، دستور مقابل دومین echo درمعرض دید کاربر قرار میگیرد.
حال نوبت به تست این اسکریپت میرسد؛ اسکریپتهای فوق را در فایلی تحتعنوان ifscript.sh ذخیره کرده، ابتدا بااستفاده از دستور chmod +x ifscript.sh این فایل را قابلاجرا کرده و درنهایت بااستفاده از دستور زیر، آنرا اجرا میکنیم:
$ ./ifscript.sh /etc/passwd
The /etc/passwd exists
همانطور که ملاحظه میشود، با دستور ifscript./ و اختصاص دادن یک پارامتر ورودی همچون etc/passwd/ این فایل را اجرا کرده و از آنجا که فایل etc/passwd/ روی سیستم وجود دارد، دستور داخل if اجرا میشود و عبارت The /etc/passwd exists نمایش داده میشود. حال یکبار دیگر دستور فوق را اجرا کرده اما اینبار مسیری که وجود خارجی روی سیستم ندارد را بهعنوان پارامتر ورودی درنظر میگیریم:
$ ./ifscript.sh /etc/passwd2
The /etc/passwd2 does not exist
میبینیم باتوجه به اینکه فایلی تحتعنوان passwd2 روی سیستم وجود ندارد، دستور داخل else اسکریپت مدنظر اجرا میگردد و پیام The /etc/passwd2 does not exist نمایش داده میشود.
بهطورکلی، Bash یکسری دستورات شرطی مرتبط با فایلها ارائه میدهد که با دستورات شرطی if میتوانند مورد استفاده قرار گیرند که در جدول زیر مهمترین این دستورات لیست شده است:
شرط کاربرد e- چک کردن وجود یک فایل d- چک کردن وجود یک دایرکتوری f- چک کردن اینکه فایل حالت معمولی دارد؛ بهعبارت دیگر یک لینک یا دایرکتوری نیست s- چک کردن اینکه حجم فایل برابر با ۰ نیست g- چک کردن اینکه sgid فایل ست شده است u- چک کردن اینکه suid فایل ست شده است f- چک کردن اینکه فایل بهاصطلاح Readable است w- چک کردن اینکه فایل بهاصطلاح Writable است x- چک کردن اینکه فایل قابلاجرا است
برای روشنتر شدن کاربرد شرطهای فوقالذکر، فایلی میسازیم تحتعنوان isexescript.sh و اسکریپتهای زیر را داخل آن کپی میکنیم:
#! /bin/bash
file=$1
if [ -x $file ]
then
echo "The $file is executable"
fi
تنها تفاوت این اسکریپت با اسکریپت قبلی از لحاظ ساختار این است که از شرط x- استفاده کردهایم که اگر به جدول فوق نگاهی بیندازیم، متوجه میشویم که این شرط مسئول چک کردن این مسئله است که آیا فایلی که بهعنوان پارامتر ورودی درنظر گرفته میشود اصطلاحاً Executabe (قابلاجرا) است یا خیر.
برای تست کردن کارکرد این اسکریپت، پیش از هرچیز ابتدا خود این فایل را قابلاجرا کرده سپس فایلی تحتعنوان tmp.sh میسازیم اما اصلاً آنرا قابلاجرا نمیکنیم؛ حال دستور زیر را در ترمینال تاپیک کرده و اینتر میکنیم:
$ ./isexescript.sh tmp.sh
میبینیم که هیچچیزی نمایش داده نمیشود؛ حال با استفاده از دستور chmod +x tmp.sh این فایل را قابلاجرا کرده سپس دستور فوق را مجدد در ترمینال وارد کرده و اینتر میکنیم:
$ ./isexescript.sh tmp.sh
The tmp.sh is executable
میبینیم که اینبار دستور داخل if اجرا شد و این درصورتی است که میتوانیم با درنظر گرفتن یک دستور else، بهسادگی برای شرایطی که فایلی درنظر گرفته شده بهعنوان پارامتر ورودی قابلاجرا نیست، پیامی خاص را درمعرض دید کاربر قرار داد.
کاربرد دستورات شرطی if در کنار استرینگها
علاوهبر تست کردن فایلها، از دستورات if برای چک کردن استرینگها نیز میتوان استفاده کرد و برای چنین مواردی از سینتکس زیر استفاده میکنیم:
if [ string1 == string2 ] ; then
ACTION
fi
برای مثال، فایلی میسازیم تحتعنوان stringscript.sh و پیش از هرچیز، ابتدا آنرا همانطور که قبلاً توضیح داده شد قابلاجرا میکنیم؛ سپس اسکریپت زیر را داخل آن کپی میکنیم:
#! /bin/bash
# Section that reads input
echo "Enter any color code (R or Y or G):"
read COLOR
# Section that comapres the entry and displays a message
if [ "$COLOR" == "R" ]
then
echo "Stop! Leave the way for others"
elif [ "$COLOR" == "Y" ]
then
echo "GET ready; Your way will be open shortly"
elif [ "$COLOR" == "G" ]
then
echo "Go Ahead. It is your turn to go"
else
echo "Incorrect color code"
fi
حال اقدام به تست اسکریپت فوق میکنیم:
$ ./stringscript.sh
Enter any color code (R or Y or G):
میبینیم که اصطلاحاً یک Prompt (سؤال) درمعرض دیدمان قرار میگیرد که باید در پاسخ به آن، یکی از حروف Y ،R و یا G که نمایندهٔ کلمات بهترتیب Red بهمعنی «قرمز»، Yellow بهمعنی «زرد» و Green بهمعنی «سبز» است را انتخاب کنیم؛ بهطور مثال حرف G را تایپ کرده و اینتر میکنیم:
$ ./stringscript.sh
Enter any color code (R or Y or G):
G
Go Ahead. It is your turn to go
میبینیم که کامندهای قرار گرفته در شرطی که چک میکند ببیند آیا مقدار متغیر COLOR برابر با G است یا خیر اجرا شده و عبارت Go Ahead. It is your turn to go بهمعنی «برو. نوبت توست که بروی» نمایش داده میشود؛ به همین منوال اگر حروف R و Y را هم وارد کنیم، دستورات مرتبط با آنها نمایش داده خواهد شد. حال ببینیم اگر حرفی از پیش تعریف نشده همچون B را وارد کنیم چه اتفاقی میافتد:
$ ./stringscript.sh
Enter any color code (R or Y or G):
B
Incorrect color code
میبینیم که دستور else آخر اجرا میشود چراکه حرف B با هیچکدام از معیارهای تعریف شده در این برنامه همخوانی ندارد. بهعنوان مثال پایانی، یکبار هم قصد داریم همان حرف G اما اینبار بهصورت کوچک (g) را وارد نماییم:
$ ./stringscript.sh
Enter any color code (R or Y or G):
g
Incorrect color code
میبینیم که مجدد بخش مرتبط با else اجرا میشود و این درحالی است که ممکن است فکر کنید حروف G و g هردو به یک ماهیت اشاره دارند!
به خاطر داشته باشید |
در دنیای کامپیوتر، کلیهٔ حروف الفبا اعم از حروف کوچک و بزرگ بهعنوان ماهیتهایی مجزا از یکدیگر شناخته میشوند؛ لذا حروف G و g بهعنوان ۲ حرف متفاوت از یکدیگر تلقی میشوند. |
آنچه در اسکریپت فوق نیاز به توضیح دارد، مفهومی است تحتعنوان elif؛ بهطورکلی هر زمانی که ما در شرایطی باشیم که نیاز به چندین دستور شرطی if داشته باشیم، بهجای نوشتن چند شرط if بهصورت مجزا، میتوانیم از ساختار elif استفاده کرده و دستورات شرطی را با یکدیگر ادغام نماییم.
در تفسیر اسکریپت فوق بایستی بگوییم که پس از اجرا، ابتدا شرط داخل اولین if چک میشود که تست میکند ببیند آیا مقدار متغیر COLOR برابر با حرف R هست یا خیر؛ اگر این مقدار برابر بود، کامندهای مرتبط با این if اجرا میشوند و برنامه پایان مییابد و در غیر اینصورت، مفسر (Bash) بهسراغ دستور elif اول میرود که مسئول چک کردن برابری مقدار متغیر COLOR با حرف Y است. بههمین منوال کلیهٔ elifهای برنامه چک میشوند و درصورتی هم که هیچ کدام از آنها اجرا نشد، برنامه بهصورت خودکار کامندهای داخل else را اجرا میکند.
هشدار |
درصورتیکه دستور fi که در پایان دستورات شرطی میآید را فراموش کنیم بنویسیم، مفسر از ما ایراد خواهد گرفت؛ لذا همواره به یاد داشته باشیم که دستورات شرطی خود را «پایان دهیم» که بهسادگی میتوان اینکار را با کامند fi انجام داد که بهنظر میرسد از ابتدای کلمهٔ Finish گرفته شده باشد. |
کاربرد دستورات شرطی if در کنار اعداد
گاهیاوقات در اسکریپتنویسی Shell نیاز داریم تا اعداد را در دستورات شرطی تست کنیم که برای اینمنظور میتوانیم از اپراتورهای زیر استفاده کنیم:
اپراتور کاربرد eq- برابر با ne- نابرابر با gt- بزرگتر از lt- کوچکتر از ge- بزرگتر از یا برابر با le- کوچکتر از یا برابر با
سینتکس دستورات شرطی برای مقایسهٔ اعداد بهصورت زیر است:
exp1 -op exp2
برای برای درک بهتر اینگونه دستورات شرطی، برنامهای کوچک و ساده مینویسیم که در آن سن کاربر را گرفته سپس پیامی در معرض دیدش قرار میدهیم که آیا وی در دههٔ سوم زندگیاش، دههٔ چهارم زندگیاش یا دههٔ پنجم زندگیاش زندگی بهسر میبرد و یا سن وارد شده توسط وی خارج از طیف درنظر گرفته شده در برنامهٔ ما است. برای اینمنظور، فایلی تحتعنوان agescript.sh در ادیتور دلخواه خود ایجاد کرده و اسکریپتهای زیر را داخل آن وارد میکنیم:
#! /bin/bash
# prompt for a use age
echo "Please enter your age:"
read AGE
if [ "$AGE" -lt 20 ] || [ "$AGE" -ge 50 ]
then
echo "Sorry, you are out of the age range."
elif [ "$AGE" -ge 20 ] && [ "$AGE" -lt 30 ]
then
echo "You are in your 20s"
elif [ "$AGE" -ge 30 ] && [ "$AGE" -lt 40 ]
then
echo "You are in your 30s"
elif [ "$AGE" -ge 40 ] && [ "$AGE" -lt 50 ]
then
echo "You are in your 40s"
fi
ابتدا برنامهٔ فوق را اجرا کرده و نحوهٔ عملکرد آنرا مشاهده میکنیم سپس به تفسیر سورسکد آن میپردازیم؛ برای این منظور، همانطور که قبلاً توضیح داده شد ابتدا دستور chmod +x agescript.sh را اجرا میکنیم تا این فایل بهاصطلاح Executabe (قابلاجرا) شود؛ سپس دستور agescript.sh/. را در کامندلاین وارد کرده و عددی همچون ۷۵ را وارد میکنیم:
$ ./agescript.sh
Please enter your age:
75
Sorry, you are out of the age range.
میبینیم باتوجه به اینکه سن وارد شده بیش از ۵۰ است، این پیام صادر شده است. حال مجدد برنامه را اجرا کرده و اینبار عددی همچون ۲۲ را وارد میکنیم:
$ ./agescript.sh
Please enter your age:
22
You are in your 20s
سپس یکبار دیگر برنامه را اجرا کرده و اینبار عددی همچون ۳۳ را وارد میکنیم:
$ ./agescript.sh
Please enter your age:
33
You are in your 30s
درنهایت، یکبار دیگر برنامه را اجرا کرده و اینبار عددی همچون ۴۷ را وارد میکنیم:
$ ./agescript.sh
Please enter your age:
47
You are in your 40s
میبینیم که این برنامه بهدرستی کار میکند اما ساختاری در این برنامه مورد استفاده قرار گرفته که بهنوعی جدید است و آنهم چیزی نیست جز علائم || و &&؛ بهطورکلی در اکثر زبانهای برنامهنویسی و همچنین Bash، دستور || بهمعنی «یا» و دستور && بهمعنی «و» است. جدول زیر شامل برخی از مهمترین اپراتورهای بولینی است که در اسکریپتنویسی مورد استفاده قرار میگیرند:
اپراتور عملکرد توضیحات && وَ در صورتی که هر دو شرط برابر با True باشند، اسکریپت ادامه مییابد. || یا در صورتی که هریک از شرطها برابر با True باشد، اسکریپت ادامه مییابد. ! مخالف اسکریپت فقط در صورتی ادامه مییابد که شرط برابر با False گردد.
به یاد داشته باشید زمانهایی که از چندین اپراتور بولینی با استفاده از اپراتور && (به معنی و) در کنار یکدیگر استفاده میکنید، به محض اینکه شرط برابر با False (مقدار ۰ یا نادرست) گردد، پردازش متوقف میگردد. برای مثال، اگر شروط A && B && C را داشته باشیم و مقدار A برابر با True باشد اما B برابر با False، شرط C هرگز چک نخواهد شد.
همچنین در صورت استفاده از اپراتور || (به معنی یا) پردازش به محض این که یکی از شروط برابر با True شود متوقف خواهد شد. به عبارت دیگر، اگر شروط A || B || C را داشته باشیم و مقدار A برابر با False باشد اما B برابر با True باشد، شرط C هرگز چک نخواهد شد.
در تفسیر اسکریپت فوق بایستی بگوییم که در دستور if این شرط را گذاشتهایم که اگر سن کاربر کوچکتر از (lt-) و یا بزرگتر از یا برابر با (ge-) بود، عبارت .Sorry, you are out of the age range بهمعنی «متأسفانه سن شما خارج از محدودهٔ درنظر گرفته شده است.» نمایش داده شود. درواقع، هر زمانی که از || استفاده میکنیم، مادامیکه یکی از شروط برآورده شود، دستور مرتبط اجرا خواهد شد اما در مورد && اینگونه است که حتماً هردو شرط میبایست برآورده شوند.
بههمین ترتیب در کلیهٔ دستورات elif این برنامه هم از دستور && استفاده کرده و همانطور که در بالا گفته شد، در این موارد حتماً پاسخ به هردو شرط میبایست مثبت باشد تا دستور مربوطه اجرا گردد.