الحلقات Loops ضرورية في أي لغة برمجة، ولها حالات استخدام متعددة في سكربتات باش سنتعلمها معًا في هذا المقال، وسنتعرف على حلقات For و While و Until، وعلى كيفية التحكم بالحلقات باستخدام تعليمات break
و continue
، بالإضافة لطريقة كتابة الحلقات اللانهائية، وكيف أنها قد تشير في بعض الأحيان لوجود أخطاء في كتابة السكربت.
حلقات For في باش
حلقة for هي واحدة من ثلاثة أنواع من الحلقات التكرارية التي يمكننا استخدامها في سكربتات باش، وهي تكتب بطريقتين:
- حلقة for المكتوبة بأسلوب لغة C
- حلقة for المعتمدة على قائمة أو مجال محدد من العناصر
كتابة حلقة for بأسلوب لغة C في سكربتات باش
نكتب هذا النوع من حلقات for بالطريقة نفسها التي نكتبها في لغات البرمجة C و ++C وفق الصيغة العامة التالية:
for ((initialize ; condition ; increment)); do [COMMANDS] done
إذا طبقنا الصيغة العامة السابقة على المثال أدناه، فإن تنفيذ الحلقة الموجودة فيه سيعرض عبارة "Hello Friend" عشر مرات على شاشة الطرفية:
for ((i = 0 ; i < 10 ; i++)); do echo "Hello Friend" done
لنفسر الشيفرة السابقة: القيمة الابتدائية لمتغير الحلقة هي 0، وشرط التكرار أن لا تتجاوز قيمة المتغير العدد 10، ومقدار الزيادة هو 1، وبالتالي في كل مرة يتحقق فيها شرط الحلقة سيُنفذ الأمر البرمجي وهو في حالتنا عرض العبارة Hello Friend على الشاشة وتزداد قيمة متغير الحلقة i بمقدار واحد، ثم يُفحص الشرط من جديد وهكذا حتى الوصول للحد الأعلى أي 10.
وهذه نتيجة تنفيذ الحلقة:
kabary@handbook:~$ bash hello.sh Hello Friend Hello Friend Hello Friend Hello Friend Hello Friend Hello Friend Hello Friend Hello Friend Hello Friend Hello Friend
كتابة حلقة for المعتمدة على القوائم في سكربتات باش
تفيدنا حلقة for المكتوبة بهذه الطريقة في الحالات التي نتعامل فيها مع قائمة معروفة العناصر، مثل: مجموعة ملفات أو مجموعة سلاسل نصية، أو مجال محدد من الأعداد، أو مصفوفة، أو ربما مخرجات ثابتة لأمر معين أو غير ذلك، ولها الصيغة العامة التالية:
for item in [LIST]; do [COMMANDS] done
يبين المثال أدناه الحلقة نفسها التي تعاملنا معها في الفقرة السابقة ولكنها مكتوبة هذه المرة بطريقة القائمة:
for i in {1..10}; do echo "Hello Friend" done
وهذا مثال آخر حيث يعرض السكربت var.sh التالي جميع الملفات الموجودة في المجلد var/
:
#!/bin/bash for i in /var/*; do echo $i done
وسنحصل في الخرج على نتيجة تشبه ما يلي:
kabary@handbook:~$ ./var.sh /var/backups /var/cache /var/crash /var/lib /var/local /var/lock /var/log /var/mail /var/metrics /var/opt /var/run /var/snap /var/spool /var/tmp
حلقات While في باش
هذه هي الصيغة العامة لحلقة while في باش:
while [ condition ]; do [COMMANDS] done
لنطبق مثالًا عمليًّا: يعرض السكربت التالي المضاعفات العشرة الأولى للعدد 3:
#!/bin/bash num=1 while [ $num -le 10 ]; do echo $(($num * 3)) num=$(($num+1)) done
وسيكون الخرج كما يلي:
kabary@handbook:~$ ./3x10.sh 3 6 9 12 15 18 21 24 27 30
لنُحلّل السكربت أعلاه، في البداية أعطينا المتغير num
القيمة الابتدائية 1، وحددنا شرط تكرار الحلقة بأن لا تتجاوز قيمة المتغير العدد 10، وبناءً على ذلك سيُنَفَذ الأمران الموجودان في جسم الحلقة وهما أولًا إظهار ناتج ضرب قيمة المتغير num
بالعدد 3 على الشاشة، وثانيًا زيادة قيمة num
بمقدار 1، ويُعاد تنفيذهما مرارًا وتكرارًا طالما أن شرط الحلقة محقق.
حلقات Until في باش
النوع الثالث من الحلقات التكرارية باش هو until، وليس الحلقة do-while التي اعتاد عليها مبرمجو لغة C و ++C، وكما نلاحظ أدناه فالصيغة العامة لحلقة until مطابقة تمامًا لصيغة كتابة حلقة while:
until [ condition ]; do [COMMANDS] Done
ويكمن الفرق بينهما في طريقة تعامل كل حلقة مع نتيجة اختبار الشرط فيما إذا كان محققًا أو غير محقق، ففي الحلقة while يستمر التنفيذ طالما أن شرط الحلقة محقق، وعلى العكس تمامًا في الحلقة until إذ يستمر التنفيذ طالما أن الشرط غير محقق.
لنكتب الآن السكربت السابق باستخدام الحلقة until بدلًا من while، دقق جيدًا في الشرط فهو جوهر الاختلاف بين السكربتين:
#!/bin/bash num=1 until [ $num -gt 10 ]; do echo $(($num * 3)) num=$(($num+1)) done
الشرط هنا هو أن تكون قيمة المتغير num
أكبر من 10، بينما كان الشرط في سكربت while هو أن تكون قيمة المتغير num
أصغر من 10وهما كما تلاحظ عكس بعضهما تمامًا.
حالات شائعة لاستخدام الحلقات في باش
بعد أن تعرفنا على أساسيات الحلقات، سنعرض بعضًا من أشهر استخداماتها في باش:
إظهار عناصر مصفوفة بواسطة سكربت باش
تُعدّ الحلقة for خيارًا مناسبًا لعرض عناصر أي مصفوفة في باش، يمكن الرجوع لمقالنا استخدام المصفوفات في باش Bash لمعرفة كيفية إنشاء مصفوفات باش والتعامل معها.
ألقِ نظرة على السكربت prime.sh التالي، إنه يتضمن مصفوفة تسمى prime وحلقة for تمر على عناصر المصفوفة واحدًا تلو الآخر وتُظهرهم على الشاشة بواسطة الأمر echo
:
#!/bin/bash prime=(2 3 5 7 11 13 17 19 23 29) for i in "${prime[@]}"; do echo $i done
وسيكون الخرج كما يلي:
kabary@handbook:~$ ./prime.sh 2 3 5 7 11 13 17 19 23 29
استخدام break و continue في حلقات باش
تساعدنا تعليمات break
و continue
على إنهاء تنفيذ الحلقة قبل الأوان أو تخطي بعضًا من تكراراتها لأغراض تخدم برنامجنا.
توقف التعليمة break
تنفيذ الحلقة وتنقل التنفيذ إلى التعليمة التالية في البرنامج، فعلى سبيل المثال ستعرض الحلقة التالية الأعداد من واحد إلى ثلاثة فقط على شاشة الطرفية:
for ((i=1;i<=10;i++)); do echo $i if [ $i -eq 3 ]; then break fi done
وتساعدنا التعليمة continue
على تجاوز بعض التكرارات، فكلما وصل تسلسل التنفيذ إلى continue
تُهمَل الأوامر التي تليها والتي تقابل قيمًا معينة للمتغير نود تجاوزها، ويُكرر تنفيذ الحلقة بعد زيادة قيمة المتغير.
يبين السكربت odd.sh التالي كيفية استخدام continue
لتخطي الأعداد الزوجية وإظهار الأعداد الفردية فقط من بين الأعداد من صفر إلى عشرة:
#!/bin/bash for ((i=0;i<=10;i++)); do if [ $(($i % 2)) -ne 1 ]; then continue fi echo $i done
وستحصل على هذا الخرج:
kabary@handbook:~$ ./odd.sh 1 3 5 7 9
الحلقات اللانهائية في باش
الحلقات اللانهائية Infinite Loops هي حلقات دائمة التكرار بدون نهاية لأن شرط تكرارها محقق دائمًا. قد يبني المستخدم حلقات لانهائية عن قصد لأهداف معينة، لكن معظم الحلقات النهائية في واقع الأمر تظهر نتيجة أخطاء بشرية غير مقصودة.
الهدف من إنشاء الحلقة التالية مثلًا هو إظهار الأرقام من واحد إلى عشرة على شاشة الطرفية لكن بترتيب تنازلي، إذا دققنا فيها سنكتشف خطأ يوقع المستخدم ضحية تكرار لا نهائي للحلقة:
for ((i=10;i>0;i++)); do echo $i done
إذا دققنا في الكود أعلاه سنلاحظ أن مُنشئ الحلقة هنا يزيد قيمة المتغير i
بمقدار واحد بعد كل تنفيذ بدلًا من إنقاصها بمقدار واحد ليصل في النهاية إلى القيمة صفر وهي شرط انتهاء الحلقة، فحتى تعمل الحلقة بالصورة المطلوبة علينا استبدال ++i
بالتعليمة --i
لتصبح كما يلي:
for ((i=10;i>0;i--)); do echo $i done
قد تفرض علينا متطلبات العمل إنشاء حلقات لا نهائية لانتظار تحقق شروط معينة على النظام مثلًا أو لأسباب أخرى، وبصرف النظر عن السبب إذا احتجنا لإنشاء هذا النوع من الحلقات فيمكننا ذلك باستخدام إحدى الصيغ التالية.
صيغة بناء حلقة لا نهائية باستخدام حلقة for:
for ((;;)); do [COMMANDS] done
صيغة بناء حلقة لا نهائية باستخدام حلقة while:
while [ true ]; do [COMMANDS] done
الخلاصة
انتهى مقالنا الخاص بالحلقات التكرارية في سكربتات باش، عرضنا فيه الحلقات الأساسية الثلاث مع بعض الأمثلة العملية ووضحنا حالات الاستخدام الخاصة بكل حلقة، ندعوك لمتابعة المقال التالي حول الدوال في باش وتطبيق المزيد من المفاهيم المتقدمة.
ترجمة -وبتصرف- للمقال Loops in Bash.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.