ساختارهای and list و or list وسیلهای برای پردازش تعدادی فرمان متوالی فراهم مینمایند. اینها میتوانند به طور کارآمدی جایگزین if/then پیچیده تو در تو یا حتی دستورالعملهای case بشوند.
command-1 && command-2 && command-3 && ... command-nهر فرمان به نوبت اجرا میشود، به شرط آنکه فرمان قبل از آن دارای یک مقدار برگشتی true (صفر) باشد. با اولین false (غیر صفر) برگشتی، زنجیره فرمان خاتمه داده میشود (اولین فرمان برگشت دهنده false، آخرین فرمان اجرا شده است).
یک مورد استفاده جالب از یک and list دو شرطی، از نگارش قدیمی اسکریپت بازی Tetris نوشته YongYe:
equation() { #الگوریتم مرکزی به کار رفته برای دوبرابر یا نصف کردن مختصات [[ ${cdx} ]] && ((y=cy+(ccy-cdy)${2}2)) eval ${1}+=\"${x} ${y} \" }
مثال 26-1. کاربرد یک and list برای تست کردن شناسههای خط فرمان
#!/bin/bash # if [ ! -z "$1" ] && echo "Argument #1 = $1" && [ ! -z "$2" ] && \ # echo "Argument #2 = $2" then echo "At least 2 arguments passed to script." #تمام فرمانهای زنجیر شده، true برگشت میدهند. else echo "Fewer than 2 arguments passed to script." #حداقل یکی از فرمانهای زنجیر شده، false برگشت میدهد. fi #توجه کنید که if [ ! -z $1 ] کار میکند، اما مورد به #اصطلاح معادل آن، if [ -n $1 ] کار نمیکند. #اگر چه، نقلقولی کردن، آن را تعمیر میکند. #if "[ -n "$1" ]" کار میکند. #مواظب باشید! #همیشه بهتر است متغیرهایی که باید رسیدگی بشوند، نقلقول گردند. #این همان کار را با استفاده از جملههای if/then خالص انجام میدهد. if [ ! -z "$1" ] then echo "Argument #1 = $1" fi if [ ! -z "$2" ] then echo "Argument #2 = $2" echo "At least 2 arguments passed to script." else echo "Fewer than 2 arguments passed to script." fi #طولانیتر و کندتر از کاربرد یک «and list» است. exit $?
مثال 26-2. یک شناسه خط فرمان دیگر با استفاده از یک and list
#!/bin/bash ARGS=1 #تعداد شناسههای مورد انتظار. E_BADARGS=85 #مقدار برگشتی اگر تعداد شناسهها صحیح نباشد. test $# -ne $ARGS && \ #شرط شماره 1 echo "Usage: `basename $0` $ARGS argument(s)" && exit $E_BADARGS # #اگر شرط شماره 1 صحیح باشد (تعداد شناسههای اسکریپت نادرست باشد) #+آنوقت بقیه سطر اجرا میشود، و اسکریپت خاتمه مییابد. #سطر زیر فقط در صورتی اجرا میگردد که بررسی فوق ناموفق باشد. echo "Correct number of arguments passed to this script." exit 0 #برای کنترل مقدار برگشتی، بعد از خاتمه یافتن اسکریپت یک echo $? انجام بدهید.
البته، یک and list همچنین میتواند متغیرها را به یک مقدار پیشفرض تنظیم نماید.
arg1=$@ && [ -z "$arg1" ] && arg1=DEFAULT #اگر شناسه(های) خط فرمان موجود باشند، arg1 را به آنها تنظیم میکند. اما #اگر در خط فرمان شناسهای تعیین نشده باشد آن را به DEFAULT تنظیم میکند.
command-1 || command-2 || command-3 || ... command-nهر فرمان به شرط آن که فرمان قبل از آن «false» را برگشت بدهد به نوبت اجرا میشود. با اولین «true» برگشتی، زنجیره فرمان خاتمه مییابد (اولین فرمان برگشت دهنده «true»، آخرین فرمان اجرا شده است). به طور آشکاری برعکس «and list» است.
مثال 26-3. به کار بردن or listها در ترکیب با یک and list
#!/bin/bash #یک برنامه حذف نه چندان ماهرانه. #طرز کاربرد: delete filename E_BADARGS=85 if [ -z "$1" ] then echo "Usage: `basename $0` filename" exit $E_BADARGS #بدون شناسه است؟ خروج. else file=$1 #تنظیم نام فایل. fi [ ! -f "$file" ] && echo "File \"$file\" not found. \ Cowardly refusing to delete a nonexistent file." #AND LIST، برای ارایه پیغام خطا در صورت موجود نبودن فایل. #توجه، پیغام echo بعد از یک \ در سطر دوم ادامه یافته است. [ ! -f "$file" ] || (rm -f $file; echo "File \"$file\" deleted.") #OR LIST برای حذف فایل در صورت موجود بودن. #به وارونگی منطقِ فوق توجه کنید. #AND LIST بر true اجرا میشود، OR LIST بر false اجرا میگردد. exit $?
اگر فرمان نخست در یک or list «صحیح» را برگشت بدهد، آن فرمان اجرا خواهد گردید. |
#برشهای زیر از اسکریپت /etc/rc.d/init.d/single #+نوشته Miquel van Smoorenburg است که استفاده از #+لیستهای «and» و «or» را توضیح میدهند. #توضیحات جهت گذاری شده، توسط نگارنده اضافه گردیدهاند. [ -x /usr/bin/clear ] && /usr/bin/clear #اگر /usr/bin/clear وجود دارد، آنوقت فراخوانی بشود. #کنترل وجود یک فرمان قبل از فراخوانی آن فرمان، از #+پیغامهای خطا و سایر پیامدهای ناپسند پیشگیری میکند. # #اگر بخواهند چیزی را در وضعیت کاربر منفرد اجرا نمایند، میتوانند این کار را انجام بدهند... for i in /etc/rc1.d/S[0-9][0-9]* ; do #کنترل موجود بودن اسکریپت. [ -x "$i" ] || continue #اگر فایل متناظر در $PWD پیدا نشود، آنوقت #+با پرش به ابتدای حلقه «ادامه» داده شود. #رد کردن فایلهای پشتیبان و فایلهای تولید شده به وسیله rpm case "$1" in *.rpmsave|*.rpmorig|*.rpmnew|*~|*.orig) continue;; esac [ "$i" = "/etc/rc1.d/S00single" ] && continue #نام اسکریپت تنظیم میگردد، اما هنوز اجرا نمیشود. $i start done #
وضعیت خروج یک and list یا یک or list، وضعیت خروج آخرین فرمان اجرا شده است. |
ترکیبهای هوشمندانهای از لیستهای and و or امکانپذیر است، اما ممکن است به آسانی منطق کد درهم پیچیده شود و به هشیاری کامل در برابر قواعد تقدم عملگر، و اشکالیابی احتمالی گسترده نیاز داشته باشد.
false && true || echo false #false #همان نتیجه در اثر ( false && true ) || echo false #false #اما نه در مورد false && ( true || echo false ) #(چیزی منعکس نمیشود) #به گروهبندی چپ به راست و دستورالعملهای ارزیابی توجه نمایید. #به طور معمول بهتر است از چنین پیچیدگیهایی پرهیز گردد. #با تشکر از S.C.
برای نمایش تجربی کاربرد ساختارهای and/or list جهت تست کردن متغیرها، مثال A-7 و مثال 7-4 را مشاهده کنید.