مسیر
/
Bash
Bash
/
برنامه‌ی درسی
/
دستورهای شرطی
دس

دستورهای شرطی در Bash

{one: "۱ تمرین", other: "%{count} تمرین"}

درباره‌ی دستورهای شرطی

درست‌نمایی در Bash

Bash مفهوم مقادیر منطقی را ندارد. رشته و عدد داریم، و آرایه‌هایی از رشته یا عدد. پس دستورهای شرطی چگونه با «درست» و «غلط» برخورد می‌کنند؟

وضعیت خروج

دستورها وقتی به پایان می‌رسند یک «وضعیت خروج» تولید می‌کنند. وضعیت خروج یک عدد صحیح بین ۰ و ۲۵۵ است (شامل هر دو سر). Bash وضعیت خروج صفر را نشانه‌ی موفقیت می‌داند. هر وضعیت خروج دیگری نشانه‌ی شکست است.

این موضوع درباره‌ی همه‌ی دستورها صادق است، از جمله دستورهای توکار bash، کلیدواژه‌ها و توابع.

دستور if

نحوه‌ی نگارش پایه‌ی دستور if چنین است

if CONDITIONAL_COMMANDS; then TRUE_COMMANDS; else FALSE_COMMANDS; fi

با if شروع می‌شود؛ دستورهای شرط با then از دستورهای «موفقیت» جدا می‌شوند؛ و با fi پایان می‌یابد. بند else اختیاری است.

CONDITIONAL_COMMANDS می‌تواند یک دستور تنها باشد یا یک فهرست از دستورها.

CONDITIONAL_COMMANDS اجرا می‌شوند و

  • اگر وضعیت خروج صفر (موفقیت) باشد، TRUE_COMMANDS اجرا می‌شوند.
  • اگر وضعیت خروج ناصفر (شکست) باشد، FALSE_COMMANDS، در صورت وجود، اجرا می‌شوند.

شاخه‌های آبشاری را می‌توان با elif نوشت

if CONDITIONAL_COMMANDS
then TRUE_COMMANDS
elif CONDITIONAL_COMMANDS_2
then TRUE_COMMANDS_2
# more elif branches ...
else FALSE_COMMANDS
fi

پیش از واژه‌های then، elif، else و fi باید یک نقطه‌ویرگول یا یک خط جدید باشد.

برای تأکید: این وضعیت خروج دستورهای شرطی است که جریان برنامه را کنترل می‌کند. برای مثال، grep اگر تطابقی پیدا شود ۰ برمی‌گرداند و اگر تطابقی پیدا نشود ۱. گزینه‌ی -q خروجی را سرکوب می‌کند و تنها وضعیت خروج را تولید می‌کند.

if grep -q "my pattern" my_file; then echo "the pattern is found in the file"; fi

دستورهای [ و test

هیچ نحوه‌ی نگارش ویژه‌ای پیرامون CONDITIONAL_COMMANDS وجود ندارد. ممکن است به دیدن دستورهای شرطی به این شکل عادت داشته باشید:

if [ "$password" = "secure" ]; then
    echo "Welcome!"
fi

[ نحوه‌ی نگارش ویژه‌ای نیست. یک دستور است که عبارت شرطی را ارزیابی می‌کند و با وضعیت موفقیت یا شکست خارج می‌شود. مانند همه‌ی دستورها، بین آن و آرگومان‌هایش فاصله ضروری است.

[ در واقع مترادف دستور test است. این دو دقیقاً یکسان‌اند، جز اینکه آخرین آرگومان [ باید ] باشد.

عبارت‌های شرطی

درون [ و ] یک عبارت شرطی می‌نویسید. از جمله عبارت‌های شرطی معمول می‌توان به این‌ها اشاره کرد:

[ -f "$filename" ]             # file operations
[ "$string1" = "$string2" ]    # string comparisons
[ "$num1" -eq "$num2" ]        # arithmetic comparisons

عملیات‌های بسیار بیشتری هم موجود است؛ آن‌ها در بخش عبارت‌های شرطی Bash از راهنما فهرست شده‌اند.

Note

در مثال‌های بالا توجه کنید که همه‌ی متغیرها داخل نقل‌قول آمده‌اند. دستورهای test و [ دستورهایی معمولی‌اند که آرگومان‌هایشان، مانند هر دستور دیگری، در معرض تقسیم واژه و بسط نام فایل قرار دارند.

اشاره به این نکته مهم است چون عبارت‌های شرطی بسته به تعداد آرگومان‌هایی که می‌دهید متفاوت ارزیابی می‌شوند:

  • ۰ آرگومان: وضعیت خروج ناصفر است (شکست)
  • ۱ آرگومان: اگر آرگومان خالی نباشد وضعیت خروج صفر است (موفقیت)، و اگر خالی باشد ناصفر.
  • ۲ آرگومان: آرگومان اول باید یک عملگر یگانی باشد (مانند [ -z "$name" ])، یا یک ! (که وضعیت آزمون تک‌آرگومانی را نفی می‌کند)
  • و موارد بیشتر.

اگر نقل‌قول را فراموش کنید ممکن است به نتایج غیرمنتظره برسید:

str=""

# this prints "empty"
if [ -n "$str" ]; then echo "not empty"; else echo "empty"; fi

# leaving the variable unquoted results in incorrect "not empty" output
if [ -n $str ]; then echo "not empty"; else echo "empty"; fi

کلیدواژه‌ی [[

ساختار شرطی [[...]] یک دستور نیست، بلکه یک کلیدواژه است. این یعنی هرچند مانند هر دستور دیگری پردازش می‌شود، قواعد تجزیه‌ی ویژه‌ای دارد. ویژگی خاص [[ این است که متغیرهایی که درونش بسط داده می‌شوند در معرض تقسیم واژه یا بسط نام فایل نیستند. یعنی این دستور، حتی بدون نقل‌قول، همان‌طور که انتظار دارید عمل می‌کند.

if [[ -n $str ]]; then echo "not empty"; else echo "empty"; fi

[[ از همه‌ی عبارت‌های شرطی که test و [ می‌توانند پردازش کنند پشتیبانی می‌کند. علاوه بر این، [[ این موارد را فراهم می‌کند

  • عملگر تطبیق با عبارت باقاعده‌ی =~،
  • == و != که به‌عنوان عملگر تطبیق با الگوی glob عمل می‌کنند،
  • && و || به‌عنوان عملگرهای منطقی (با قاعده‌ی تجزیه‌ی ویژه)،
  • < و > به‌عنوان عملگرهای مقایسه‌ی رشته‌ی بدون نقل‌قول (قاعده‌ی تجزیه‌ی ویژه: چون این‌ها نمادهای تغییر مسیر هستند، در [ باید اسکیپ شوند).

دیدگاه رایجی است که این ویژگی‌های خاص آن‌قدر سودمندند که باید منحصراً از [[ استفاده کرد. (برای مثال، راهنمای سبک‌نگارش Shell گوگل.)

دستور case

case یکی دیگر از دستورهای کنترل جریان است. مانند دستور switch در زبان‌های دیگر است.

case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac

WORD با هر PATTERN تطبیق داده می‌شود. وقتی یکی تطبیق پیدا کند، COMMANDS اجرا می‌شوند.

read -p "Guess the secret word: " word
case "$word" in
    secret) echo "Yes, you guessed it!" ;;
    ??????) echo "That's the right number of letters." ;;
    s*)     echo "You guessed the first letter." ;;
    *)      echo "Not even close! Try again." ;;
esac

هر بند COMMANDS باید با دو نقطه‌ویرگول، ;;، پایان یابد.

Note

۱. جایگزین‌هایی وجود دارند که امکان اجرای پشت‌سرهم دستورها و ادامه‌ی تطبیق الگو را فراهم می‌کنند. برای جزئیات راهنما را ببینید. ۲. به یاد بیاورید که درباره‌ی الگوها در بخش بسط نام فایل از مفهوم Quoting صحبت کردیم.

ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود