المسارات
/
Bash
Bash
/
المنهج
/
الجمل الشرطية
ال

الجمل الشرطية في Bash

{zero: "لا توجد تمارين", one: "1 تمرين", two: "تمرينان", few: "%{count} تمارين", many: "%{count} تمرينًا", other: "%{count} تمرين"}

نبذة عن الجمل الشرطية

مفهوم الصدقية في Bash

لا يمتلك 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، وعندئذٍ:

  • إذا كانت حالة الخروج صفرًا (نجاح)، تُنفَّذ 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 القيمة 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 الشرطية من الدليل.

Note

في الأمثلة أعلاه، لاحظ أن جميع المتغيرات محاطة بعلامات اقتباس. فالأمران test و[ أمران عاديان، حيث تخضع الوسائط لتقسيم الكلمات وتوسيع أسماء الملفات كأي أمر آخر.

من المهم الإشارة إلى هذا لأن التعبيرات الشرطية تُقيَّم بطرق مختلفة بناءً على عدد الوسائط التي تمررها:

  • 0 وسائط: تكون حالة الخروج غير صفرية (فشل).
  • وسيط واحد: تكون حالة الخروج صفرًا (نجاح) إذا لم تكن الوسيطة فارغة، وغير صفر إذا كانت فارغة.
  • وسيطان: يجب أن يكون الوسيط الأول عاملًا أحاديًا (مثل [ -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 بـفاصلتين منقوطتين، ;;.

Note
  1. توجد بدائل تتيح تنفيذ الأوامر بالانتقال إلى الفرع التالي، واستمرار مطابقة الأنماط. راجع الدليل للتفاصيل.
  2. تذكّر أننا تحدثنا عن الأنماط في قسم توسيع أسماء الملفات من مفهوم الاقتباس.
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة