فهرست مطالب
چکیده
در این فصل در باره استفاده از شرطها در اسکریپتهای Bash صحبت میکنیم. این صحبت مباحث زیر را شامل میشود:
دستور if
کاربرد وضعیتهای خروج یک فرمان
مقایسه و بررسی ورودی و فایلها
ساختارهای if/then/else
ساختارهای if/then/elif/else
کاربرد پارامترهای موقعیتی
دستورات if تو در تو
عبارتهای منطقی
کاربرد جملات case
گاهی اوقات در اسکریپت پوسته لازم است نسبت به موفقیت یا شکست یک فرمان، گروه متفاوتی از فعالیتها را برای انجام شدن تعیین کنید. ساختار if تعیین اینگونه شرایط را برای شما ممکن میسازد.
فشردهترین ترکیب دستور if چنین است:
if TEST-COMMANDS; then CONSEQUENT-COMMANDS; fi
لیست TEST-COMMAND اجرا میشود، و اگر کد برگشتی آن صفر باشد، لیست CONSEQUENT-COMMANDS اجرا میشود. کد برگشتی، وضعیت خروج آخرین فرمان اجرا شده است، یا در صورتیکه نتیجه بررسی شرط صحیح باشد صفر است.
لیست TEST-COMMAND اغلب بررسیهای مقایسهای عددی یا رشتهای را در بر میگیرد، اما میتواند هر دستوری نیز باشد، که در صورت اجرای موفق کد صفر و در صورت شکست برخی کدهای وضعیت دیگر را بازگرداند. غالباً عبارتهای یکانی برای آزمودن وضعیت یک فایل استفاده میشود. اگر شناسه FILE
به یکی از شکلهای اصلی /dev/fd/N
باشد، آنوقت توصیفگر فایل شماره “N” کنترل میشود. stdin
، stdout
و stderr
و توصیفگرهای مربوطه آنها نیز میتوانند برای بررسیها استفاده شوند.
جدول زیر شامل خلاصه ای از “ورودیهای” شناخته شده که دستور یا لیست دستورات TEST-COMMAND را تشکیل میدهند، میباشد. این ورودیها برای نشان دادن آنکه عبارت شرطی هستند در کروشهها قرار دارند.
جدول 7.1: عبارتهای ورودی
عبارتها میتوانند با استفاده از عملگرهای زیر که با ترتیب کاهش اولویت لیست شدهاند، با هم ترکیب شوند:
جدول 7.2: ترکیب عبارتها
عملگر | نتیجه |
---|---|
[ ! EXPR ] | اگر EXPR غلط باشد، صحیح است. |
[ ( EXPR ) ] | مقدار EXPR را برمیگرداند. این میتواند برای ابطال اولویت معمولی عملگرها به کار برود. |
[ EXPR1 -a EXPR2 ] | اگر هر دوی EXPR1 و EXPR2 صحیح باشند، صحیح است. |
[ EXPR1 -o EXPR2 ] | در صورتیکه هر کدام از EXPR1 یا EXPR2 صحیح باشند، صحیح است. |
فرمان داخلی [ (یا test) با استفاده از یک مجموعه قواعدبر اساس تعداد شناسهها، عبارتهای شرطی را ارزیابی میکند. اطلاعات بیشتر در باره این موضوع را میتوانید در مستندات Bash پیدا کنید. درست مثل if که با fi بسته میشود، کروشه باز باید پس از آن که شرطها لیست شدهاند با علامت برعکس آن بسته شود.
لیست CONSEQUENT-COMMANDS که به دنبال جمله then آمده میتواند هر دستور معتبر یونیکس ، هر برنامه اجرایی، هر اسکریپت اجرایی پوسته، یا هر دستور پوسته، به استثنای بستن با fi باشد. این اهمیت دارد که به خاطر بسپارید که then و fi در پوسته به عنوان جملاتی که باید جدا از یکدیگر باشند درنظر گرفته شدهاند. بنابراین، موقعی که در خطفرمان صادر میشوند باید با کاراکتر سمیکالن جدا شوند.
در یک اسکریپت، بخشهای مختلف دستور if معمولاً بهخوبی جدا میشوند. در اینجا یک جفت مثال ساده.
مثال اول وجود یک فایل را بررسی میکند:
anny ~>
catmsgcheck.sh
#!/bin/bash echo "This scripts checks the existence of the messages file." echo "Checking..." if [ -f /var/log/messages ] then echo "/var/log/messages exists." fi echo echo "...done."anny ~>
./msgcheck.sh This scripts checks the existence of the messages file. Checking... /var/log/messages exists. ...done.
برای افزودن به فایلهای پیکربندی Bash خودتان:
# These lines will print a message if the noclobber option is set: if [ -o noclobber ] then echo "Your files are protected against accidental overwriting using redirection." fi
محیط | |
---|---|
مثال فوق وقتی در خطفرمان وارد شود نیز کار خواهد کرد:
هرچند که، اگر شرطهایی که وابسته به محیط هستند را بررسی میکنید، ممکن است موقع اجرا در اسکریپت و یا خطفرمان نتایج متفاوتی بهدست آورید، چرا که اسکریپت یک پوسته جدید را باز میکند، که ممکن است در آن متغیرها و گزینههای مورد انتظار به طور خودکار برقرار نگردند,. |
متغیر ?
وضعیت خروج فرمان اجرا شده قبلی ( آخرین پردازش کامل شده پیشزمینه ) را در خود نگاه میدارد.
مثال زیر یک بررسی ساده را نشان میدهد:
anny ~>
if[ $? -eq 0 ]
More input>
then echo'That was a good job!'
More input>
fi That was a good job!anny ~>
مثال زیر نشان میدهد که TEST-COMMANDS میتواند هر فرمان یونیکسی که یک کد وضعیت خروج برمیگرداند،باشد، و آن if دوباره یک کد وضعیت صفر برمیگرداند:
anny ~>
if! grep $USER
/etc/passwd
More input>
then echo"your user account is not managed locally"
; fi your user account is not managed locallyanny >
echo$?
0anny >
همین نتیجه به طریق زیر نیز میتواند حاصل گردد:
anny >
grep$USER
/etc/passwd
anny >
if[ $? -ne 0 ]
; then echo"not a local account"
; fi not a local accountanny >
مثال زیر مقایسههای عددی را به کار میبرد:
anny >
num
=`wc -l work.txt`
anny >
echo$num
201anny >
if[ "$num" -gt "150" ]
More input>
then echo ; echo"you've worked hard enough for today."
More input>
echo ; fi you've worked hard enough for today.anny >
این اسکریپت توسط cron هر یکشنبه اجرا میشود. اگر عدد هفته زوج باشد، یادآوری میکند که سطل زباله را بیرون بگذارید:
#!/bin/bash # Calculate the week number using the date command: WEEKOFFSET=$[ $(date +"%V") % 2 ] # Test if we have a remainder. If not, this is an even week so send a message. # Else, do nothing. if [ $WEEKOFFSET -eq "0" ]; then echo "Sunday evening, put out the garbage cans." | mail -s "Garbage cans out" your@your_domain.org fi
یک مثال از مقایسه رشتهها برای بررسی ID:کاربر
if [ "$(whoami)" != 'root' ]; then echo "You have no permission to run $0 as non-root user." exit 1; fi
در Bash، میتوانید این ساختار را کوتاه کنید. معادل فشرده مثال فوق به صورت زیر میباشد:
[ "$(whoami)" != 'root' ] && ( echo you are using a non-privileged account; exit 1 )
مشابه عبارت “&&” که اشاره میکند اگر نتیجه بررسی صحیح باشد چهکاری انجام شود، و“||” که تعیین میکند اگر نتیجه غلط بود چه کاری انجام شود.
عبارتهای منظم نیز در مقایسهها میتوانند به کار روند:
anny >
gender
="female"
anny >
if[[ "$gender" == f* ]]
More input>
then echo"Pleasure to meet you, Madame."
; fi Pleasure to meet you, Madame.anny >
برنامهنویسان حقیقی | |
---|---|
اکثر برنامهنویسان ترجیح میدهند دستور داخلی test را یه کار ببرند، که معادل کروشهها برای مقایسه هستند، مانند این: test "$(whoami)" != 'root' && (echo you are using a non-privileged account; exit 1) |
خارج نشود؟ | |
---|---|
اگر در یک زیرپوسته exit را فراخوانی کنید، متغیرها را به پوسته والد عبور نمیدهد. اگر میحواهید Bash به یک زیرپوسته ابشعاب نکنداز { and } به جای ( and ) استفاده کنید. |
صفحههای info از Bash را برای انطباق الگو با ساختارهای “(( EXPRESSION ))” و “[[ EXPRESSION ]]” جهت اطلاعات بیشتر ملاحظه کنید.