Tournez cent tours, tournez mille tours, Tournez souvent et tournez toujours . . . --Verlaine |
فرمانهای اثر گذار بر رفتار حلقه
فرمانهای کنترل حلقه break و continue[1] به طور دقیق با همتاهایشان در سایر زبانهای برنامهنویسی مطابقت دارند. فرمان break حلقه را خاتمه میدهد (از آن بیرون میرود)، در حالیکه continue با پرش از روی تمام فرمانهای باقیمانده در آن دور بخصوص حلقه، باعث جهیدن به تکرار بعدی حلقه میگردد.
مثال 11-21. اثرات break و continue در یک حلقه
#!/bin/bash LIMIT=19 # echo echo "Printing Numbers 1 through 20 (but not 3 and 11)." a=0 while [ $a -le "$LIMIT" ] do a=$(($a+1)) if [ "$a" -eq 3 ] || [ "$a" -eq 11 ] #به غیر از 3 و 11 then continue # fi echo -n "$a " #این سطر برای 3 و 11 اجرا نمیشود. done # #چرا حلقه تا 20 چاپ میکند؟ echo; echo echo Printing Numbers 1 through 20, but something happens after 2. # #همان حلقه، اما با جایگزینی break به جای continue a=0 while [ "$a" -le "$LIMIT" ] do a=$(($a+1)) if [ "$a" -gt 2 ] then break # fi echo -n "$a " done echo; echo; echo exit 0
فرمان break ممکن است به طور اختیاری یک پارامتر بگیرد. یک break ساده فقط درونیترین حلقهای را که در آن جاسازی گردیده است، خاتمه میدهد، اما یک break N از N رده حلقه بیرون میرود.
مثال 11-22. بیرون رفتن از چند رده حلقه
#!/bin/bash # #"break N" از N سطح حلقهها بیرون میرود. for outerloop in 1 2 3 4 5 do echo -n "Group $outerloop: " # for innerloop in 1 2 3 4 5 do echo -n "$innerloop " if [ "$innerloop" -eq 3 ] then break #break 2 را برای دیدن اینکه چه میشود، امتحان کنید. #( از هر دو حلقه داخلی و خارجی بیرون میرود. ) fi done # echo done echo exit 0
فرمان continue نیز، همانند break، به طور اختیاری یک پارامتر قبول میکند. یک continue ساده، تکرار فعلی داخل حلقهاش را پیش از موقع قطع کرده و دور بعدی را شروع میکند. یک continue N تمام تکرارهای باقیمانده سطح حلقهاش را فسخ میکند و تکرار بعدی حلقه را در N سطح بالاتر ادامه میدهد.
مثال 11-23. ادامه در سطح بالاتر حلقه
#!/bin/bash #فرمان "continue N" در Nمین سطح حلقه ادامه میدهد. for outer in I II III IV V # do echo; echo -n "Group $outer: " # for inner in 1 2 3 4 5 6 7 8 9 10 # do if [[ "$inner" -eq 7 && "$outer" = "III" ]] then continue 2 # # #"continue" ساده تعویض کنید. fi echo -n "$inner " #7 8 9 10 در «گروه III» منعکس نخواهند شد. done # done echo; echo # #یک کاربرد با معنی برای "continue N" در یک اسکریپت طرح کنید. exit 0
مثال 11-24. کاربرد continue N در یک وظیفه واقعی
#Albert Reiner یک نمونه از چگونگی استفاده از "continue N" را ارایه میکند: # # #+ #+ #+ #آنوقت معمولاً چیزی مشابه مورد زیر را با هر دستگاه nohup میکنم: while true do for n in .iso.* do [ "$n" = ".iso.opts" ] && continue beta=${n#.iso.} [ -r .Iso.$beta ] && continue [ -r .lock.$beta ] && sleep 10 && continue lockfile -r0 .lock.$beta || continue echo -n "$beta: " `date` run-isotherm $beta date ls -alF .Iso.$beta [ -r .Iso.$beta ] && rm -f .lock.$beta continue 2 done break done exit 0 #جزییات، محصوصاً sleep N ویژه برنامه کاربردی #+ while true do for job in {pattern} do {job already done or running} && continue {mark job as running, do job, mark job as done} continue 2 done break #یا چیزی مانند 'sleep 600' برای اجتناب از خاتمه یافتن. done #بدین طریق اسکریپت فقط موقعی متوقف خواهد شد که کار دیگری برای اجرا وجود #+نداشته باشد (از جمله کارهایی که در حین اجرا اضافه گردیدهاند). از طریق #+کاربرد فایلهای قفل مناسب میتواند بدون دونسخهای کردن محاسبات (که در مورد #+من بیش از ساعتها کار میبرد، از اینرو میخواهم از آن پرهیز نمایم) به طور #+همزمان در چندین ماشین اجرا بشود. همچنین چون جستجو همیشه دوباره از ابتدا #+شروع میشود، شخص میتواند اولویت در نام فایلها را نیز کد گذاری نماید. #+البته شخص میتواند این کار را بدون «continue 2» نیز انجام دهد، اما آنوقت #+میباید به طور واقعی کنترل میکرد که به هر حال کار معینی انجام شده یا خیر #+(برای اینکه ما باید بلافاصله سراغ کار بعدی میرفتیم) #+(در حالتی که قبل از کنترل برای یک کار جدید، خاتمه بدهیم یا به مدت طولانی #+غیر فعال بشویم.)
درک ساختار continue N دشوار و استفاده از آن در یک مضمون معنادار، مهارتآمیز است. شاید پرهیز از آن مناسبتر باشد. |
[1] |
این فرمانها builtin پوسته هستند، در حالیکه سایر فرمانهای حلقه، از قبیل while و case، کلمه کلیدی هستند. |