للـ Bash شكلان من الحلقات:
for
لكي نمرّ على قائمة من العناصر، نستخدم حلقة for.
for varname in words; do COMMANDS; done
يُوسَّع words باستخدام تقسيم الكلمات وتوسيع أسماء الملفات (الذي تعلّمناه في مفهوم الاقتباس).
وتُسنَد كل كلمة إلى varname بالتناوب، ثم تُنفَّذ الأوامر.
إليك بعض الأمثلة التي تُبيّن متى تكون حلقة for مفيدة:
تنفيذ بعض الأوامر على مجموعة من الملفات.
# source all the bash library files in the current directory
for file in ./*.bash; do
source "$file"
done
تنفيذ أمر ما على كل معامل من معاملات سكربت أو دالة.
for arg in "$@"; do
echo "argument: ${arg}"
done
تنفيذ أمر ما لكل كلمة مفصولة بمسافة بيضاء في خرج أمر.
for i in $(seq 10); do
echo "${i} squared is $((i * i))"
done
سنرى بعض التحذيرات حول هذا الأسلوب لاحقًا.
for الحسابيةتوفّر Bash بالفعل حلقة حسابية. سيبدو هذا مألوفًا إلى حدٍّ ما للغات البرمجة الأخرى.
for ((INITIALIZATION; CONDITION; INCREMENT)); do COMMANDS; done
تمثّل الأقواس الهلالية المزدوجة في Bash سياقًا حسابيًا (سنرى المزيد عن الحساب في Bash في مفهوم لاحق).
يمكن كتابة المثال السابق الذي يستخدم seq هكذا:
for ((i = 1; i <= 10; i++)); do
echo "${i} squared is $((i * i))"
done
for
هذا نمط مضاد ستراه كثيرًا: المرور على خرج cat.
for line in $(cat some.file); do
do_something_with "$line"
done
هذا خطأ لسببين.
for هذه تمرّ على الكلمات في الملف، لا على الأسطر.كما تعلّمنا في مفهوم الاقتباس، يمكن التحكم في تقسيم الكلمات عبر المتغير IFS، ويمكن إيقاف توسيع أسماء الملفات.
لكن هذا الحل غالبًا ما يكون هشًّا.
for ليست الأسلوب الصحيح للمرور على أسطر ملف.
الأسلوب الاصطلاحي لقراءة ملف هو استخدام حلقة while.
while
استخدم while لتكرار تسلسل من الأوامر طالما أن شرطًا ما صحيح.
while CONDITION_COMMANDS; do COMMANDS; done
وكما هو الحال مع if (كما تعلّمنا في مفهوم الشروط، لا توجد صياغة خاصة لـ CONDITION_COMMANDS.
فستحدّد حالة خروج قائمة الأوامر ما إذا كانت "صحيح" أو "خطأ".
يخرج الأمر break من الحلقة.
ويستأنف التنفيذ من الأمر الذي يلي المُنهي done الخاص بالحلقة.
ينتقل الأمر continue إلى التكرار التالي من الحلقة.
كما ذكرنا، حلقة while هي الأسلوب الاصطلاحي لقراءة ملف.
while IFS= read -r line; do
do_something_with "$line"
done < some.file
يُقدَّم محتوى الملف كدخل إلى الحلقة عبر إعادة التوجيه <.
يُرجع الأمر read القيمة "صحيح" إذا استطاع قراءة سطر كامل من دخله.
وعندما يُستهلك الدخل، أو إذا انتهى السطر الأخير دون سطر جديد في آخره، فإن read تُرجع "خطأ".
الأسلوب الاصطلاحي حقًّا لقراءة أسطر ملف، حتى لو لم ينتهِ السطر الأخير بسطر جديد، هو
while IFS= read -r line || [[ -n "$line" ]]; do ...
يخبر الخيار -r الأمر read بألّا يستبدل متتاليات الشرطة المائلة العكسية: فالشرطة المائلة العكسية مجرد محرف عادي.
يُسنِد IFS= السلسلة النصية الفارغة إلى IFS فقط لمدة تنفيذ أمر read.
وهذا يوقف تقسيم الكلمات مؤقتًا، بحيث تُحفظ أي مسافات بيضاء في بداية السطر النصي القادم أو نهايته.
untilيُكرّر التركيب until تسلسلًا من الأوامر طالما أن شرطًا ما خطأ.
وتتكرر الحلقة حتى يصبح الشرط صحيحًا.
until CONDITION_COMMANDS; do COMMANDS; done
من النادر استخدام until.
الأكثر شيوعًا هو استخدام حلقة "while not".
while ! CONDITION_COMANDS; do ...
أحيانًا تريد أن تكرّر إلى ما لا نهاية. إليك أسلوبان لفعل ذلك.
حلقة while بشرط تكون حالة خروجه دائمًا ناجحة
while true; do ...
حلقة for حسابية بتعابير فارغة
for ((;;)); do ...
do-whileلا يوجد تركيب صريح لـ do-while، لكن يمكنك تحقيق النتيجة نفسها:
while true; do
COMMANDS
if END_CONDITION; then
break
fi
done