لا يمتلك Bash مفهوم القيم المنطقية. فهناك السلاسل النصية والأعداد، ومصفوفات السلاسل النصية أو الأعداد. فكيف تتعامل الأوامر الشرطية مع الصحيح والخطأ؟
تُنتج الأوامر حالة خروج عند انتهائها. وحالة الخروج عدد صحيح بين 0 و255، شاملًا الطرفين. ويعتبر Bash أن حالة الخروج التي قيمتها صفر تمثّل النجاح. وأي حالة خروج أخرى تمثّل الفشل.
وينطبق هذا على جميع الأوامر، بما فيها أوامر bash المدمجة، والكلمات المفتاحية، والدوال.
if
الصيغة الأساسية للأمر if هي
if CONDITIONAL_COMMANDS; then TRUE_COMMANDS; else FALSE_COMMANDS; fi
يبدأ بـif؛ وتفصل then بين أوامر الشرط وأوامر "النجاح"؛ وينتهي بـfi.
وفرع else اختياري.
يمكن أن تكون CONDITIONAL_COMMANDS أمرًا واحدًا، أو قائمة أوامر.
تُنفَّذ CONDITIONAL_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 القيمة 0 إذا وُجد تطابق، و1 إذا لم يوجد تطابق.
ويمنع الخيار -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 الشرطية من الدليل.
في الأمثلة أعلاه، لاحظ أن جميع المتغيرات محاطة بعلامات اقتباس.
فالأمران 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،&& و|| كعاملين منطقيين (قاعدة تحليل خاصة)،< و> كعاملي مقارنة سلاسل نصية "مجرّدين" (قاعدة تحليل خاصة: لأنهما رمزا إعادة توجيه، يجب تهريبهما في [).ومن الشائع أنه يُعتقد أن هذه الميزات الخاصة تقدّم فائدة كبيرة لدرجة أنه ينبغي استخدام [[ حصرًا.
(على سبيل المثال، Google Shell Style Guide.)
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 بـفاصلتين منقوطتين، ;;.