در این بخش با حلقه‌های for، while و while آشنا خواهید شد. چرا حلقه for در حلقه bash خروجی For Director اجرا نمی شود

چرخه برایکمی متفاوت از آنالوگ در سایر زبان های برنامه نویسی است. اول از همه، این امکان را برای شما فراهم می کند که اقدامات متوالی را روی "کلمات" در یک رشته انجام دهید.

چرخه در حالی کهاگر عبارت تست درست باشد، یک قطعه کد را اجرا می کند. و اگر نادرست باشد متوقف می شود (یا یک شکست حلقه مشخص شده در داخل کد اجرایی رخ می دهد).

چرخه تا زمانتقریباً مشابه حلقه while است. تنها تفاوت این است که اگر عبارت مورد آزمایش اشتباه باشد، کد اجرا می شود.

اگر فرض کنید که while و while بسیار شبیه هم هستند، درست می گویید.

7.1 مثال برای حلقه

#! / bin / bash برای i در $ (ls); do echo مورد: $ انجام دادم

در خط دوم، i را به عنوان متغیری نشان می دهیم که مقادیر مختلف موجود در $ (ls) را دریافت می کند.

خط سوم در صورت لزوم می تواند طولانی تر باشد. یا ممکن است قبل از انجام چندین خط وجود داشته باشد (خط 4).

"done" (خط 4) نشان می دهد که کدی که از مقدار $ i استفاده می کند به پایان می رسد و $ i یک مقدار جدید دریافت می کند.

این فیلمنامه اهمیت کمی دارد. استفاده مفیدتر از حلقه for استفاده از آن برای انتخاب تنها فایل های خاص در مثال قبلی است.

7.2 C مانند برای

فیش اضافه کردن این فرم حلقه را پیشنهاد کرد. این یک حلقه for است که بیشتر شبیه به for در C، Perl و موارد مشابه است.

#! / bin / bash برای i در `sq 1 10`; echo $ انجام دادم

7.3 مثالی از حلقه while:

#! / bin / bash COUNTER = 0 در حالی که [$ COUNTER -lt 10]; do echo شمارنده $ COUNTER است اجازه دهید COUNTER = COUNTER + 1 انجام شود

این اسکریپت ساختار شناخته شده (در C، Pascal، Perl و غیره) "for" را شبیه سازی می کند.

خلاصه ای سریع از تفاوت در انواع چرخه:

for - تا زمانی که اشیایی برای اجرا وجود داشته باشد یک عمل را انجام می دهد (مثلاً خواندن یک جریان از stdin، فایل یا تابع).
while - عمل تا زمانی را انجام می دهد وضعیتدرست است؛
تا - اجرا خواهد شد تا وضعیتدرست نخواهد شد، یعنی. در حالی که دروغ است.

حلقه FOR

این نسخه از یک اسکریپت را با یک حلقه در نظر بگیرید:

$ cat loop.sh #! / bin / bash برای متغیر در `ls -1` do echo" $ متغیر "انجام شد

نحو بسیار ساده است و به وضوح در مثال نشان داده شده است:

متغیر for (شروع حلقه) (متغیری که باید روی آن اجرا شود) در (ارسال جریان به حلقه) `ls -1` (فرمانی که باید اجرا شود و به متغیر متغیر $ ارسال شود). Do و done "بدنه" حلقه هستند که در آن اقدامات اصلی روی داده های دریافتی انجام می شود و اکو "$ متغیر" عمل واقعی انجام شده توسط حلقه است.

اکنون مثال را کمی تغییر می دهیم و به جای اینکه به صراحت دستور را مشخص کنیم، متغیر دوم را اعمال می کنیم:

$ cat loop.sh #! / bin / bash ls = `ls -1` برای متغیر در $ ls do echo" $ متغیر "انجام شد"

اکنون دستور ls -1 در یک متغیر جداگانه ارسال می شود که امکان انعطاف پذیری بیشتری را در کار با حلقه فراهم می کند. به جای یک متغیر در یک حلقه، می توانید از یک تابع نیز استفاده کنید:

$ cat loop.sh #! / bin / bash lsl () (ls -1) برای متغیر در `lsl` do echo" $ متغیر "انجام شد

شرط اصلی حلقه for این است که تا زمانی که دستور ارسال شده به آن حاوی اشیایی برای عمل باشد، اجرا خواهد شد. بر اساس مثال بالا - تا زمانی که فایل هایی برای نمایش در لیست ls -1 وجود دارد - حلقه آنها را به یک متغیر منتقل می کند و "بدنه حلقه" را اجرا می کند. به محض پایان یافتن لیست فایل های دایرکتوری، حلقه به اجرای خود پایان می دهد.

بیایید مثال را کمی پیچیده کنیم.

فهرست شامل لیستی از فایل ها است:

$ ls -1 file1 file2 file3 file4 file5 loop.sh nofile1 nofile2 nofile3 nofile4 nofile5

ما باید از بین آنها فقط آنهایی را انتخاب کنیم که کلمه "" را ندارند. نه«:

$ cat loop.sh #! / bin / bash lsl = `ls -1` برای متغیر در $ lsl do echo" $ متغیر "| grep -v "نه" انجام شد $ ./loop.sh file1 file2 file3 file4 file5 loop.sh

در حلقه، می توانید از عبارات شرطی نیز استفاده کنید ( عبارات شرطی) [...] برای بررسی شرایط و یک دستور break برای قطع کردن حلقه در صورت ایجاد شرط.

این مثال را در نظر بگیرید:

$ cat loop.sh #! / bin / bash lsl = `ls -1` برای متغیر در $ lsl اگر [$ variable! =" loop.sh "] سپس echo" $ متغیر "| grep -v "نه" دیگر شکست فی انجام شد

حلقه تا زمانی که با فایل loop.sh مواجه شود ادامه خواهد داشت. به محض اینکه اجرای حلقه به این فایل رسید، حلقه با دستور break قطع می شود:

$ ./loop.sh file1 file2 file3 file4 file5

مثال دیگر استفاده از عملیات حسابی درست قبل از اجرای بدنه حلقه است:

$ cat loop.sh #! / bin / bash برای ((شمارش = 1؛ شمارش<11; count++)) do echo "$count" done

در اینجا ما سه دستور کنترل را تنظیم می کنیم - count = 1، شرط کنترل - در حالی که count کمتر از 11 است، و دستور اجرا - count +1:

حلقه های WHILE و UNTIL

یک مثال ساده که به خوبی نشان می دهد که حلقه while چگونه کار می کند:

$ cat loop.sh #! / bin / bash count = 0 در حالی که [$ count -lt 10] انجام دهید ((count ++)) echo $ count تمام شد

متغیر $ count را صفر می کنیم و سپس حلقه whi le را با شرط "در حالی که $ count کمتر از ده است، حلقه را اجرا کنید" شروع می کنیم. در بدنه حلقه، اجرا می کنیم افزایش پسوندبه متغیر $ count 1+ کنید و نتیجه را در stdout چاپ کنید.

نتیجه اجرا:

$ ./loop.sh 1 2 3 4 5 6 7 8 9 10

به محض اینکه مقدار متغیر $ count به 10 تبدیل شد، حلقه به پایان رسید.

یک مثال خوب از یک حلقه "بی نهایت" که نحوه عملکرد while را نشان می دهد:

$ cat loop.sh #! / bin / تعداد bash = 10 در حالی که [1 = 1] انجام ((شمار ​​++)) echo $ count انجام شد $ ./loop.sh ... 5378 5379 5380 5381 5382 5383 ^ C

حلقه تا به همین ترتیب کار می کند، اما "در جهت مخالف":

$ cat loop.sh #! / bin / تعداد bash = 0 تا زمانی که [$ count -gt 10] انجام شود ((count ++)) echo $ count تمام شد

در اینجا ما یک شرط مشابه را تعیین می کنیم، اما به جای "در حالی که متغیر کمتر از 10 است" - "تا زمانی که متغیر بیشتر از 10 شود" را نشان می دهیم. نتیجه اجرا:

$ ./loop.sh 1 2 3 4 5 6 7 8 9 10 11

اگر مثال بالا از یک "حلقه بی نهایت" با استفاده از - o اجرا شود، بر خلاف while:

$ cat loop.sh #! / bin / تعداد bash = 10 تا [1 = 1] انجام دهید ((شمارش ++)) echo $ count انجام شد $ ./loop.sh $

زیرا " وضعیت"در ابتدا" واقعا"- بدنه حلقه اجرا نمی شود.

مانند حلقه for، توابع را می توان در while و while استفاده کرد. به عنوان مثال، یک حلقه از یک اسکریپت واقعی که وضعیت سرور را بررسی می کند تامکت(PID در سیستم گرفته می شود SLES، ممکن است در سیستم های دیگر متفاوت باشد)، یک نسخه کمی ساده شده:

$ cat loop.sh #! / bin / bash check_tomcat_status () (RUN = `ps aux | grep tomcat | grep -v grep | grep java | awk" (چاپ $2) "`) در حالی که check_tomcat_status را اگر [-n" انجام دهید $ RUN "] سپس printf" اخطار: Tomcat همچنان با PID $ RUN در حال اجرا است." else printf "تامکت متوقف شد، ادامه داشت... nn" شکست فی انجام شد

نتیجه اجرا:

$ ./loop.sh اخطار: تامکت همچنان با PID 14435 26548 در حال اجراست. اخطار: تامکت هنوز با PID 14435 در حال اجراست 26548. اخطار: تامکت همچنان با PID 14435 26548 در حال اجرا است. اخطار: Tomcat هنوز با PID 14435 در حال اجرا است. اخطار: Tomcat هنوز با PID 14435 در حال اجرا است. هشدار: Tomcat هنوز با PID 14435 در حال اجرا است. در حال اجرا با PID 14435 26548. اخطار: Tomcat هنوز با PID 14435 26548 در حال اجرا است. هشدار: Tomcat هنوز با PID 14435 26548 در حال اجرا است. اخطار: Tomcat همچنان با PID 14435 در حال اجرا است.

نسخه کامل:

Check_tomcat_status () (RUN = `ps aux | grep tomcat | grep -v grep | grep java | awk" (چاپ $2) "`) در حالی که check_tomcat_status; اگر [-n "$ RUN"] را انجام دهید، سپس printf "WARNING: Tomcat همچنان با PID $ RUN در حال اجراست. متوقفش کنید؟" پاسخ دهید "توقف Tomcat..." "در حال ادامه نصب..." && $ CATALINA_HOME / bin / shutdown. sh 2 &> 1 / dev / null || شکستن خواب 2 اگر [-n "$ RUN"] سپس printf "تامکت هنوز در حال اجراست. بکشید؟" پاسخ دهید "کشتن تامکت ..." "در حال نصب... n" && kill $ RUN || break sleep 2 fi else printf "تامکت متوقف شد، ادامه داشت... nn" شکستن فی انجام شد

تابع پاسخ در مقاله توضیح داده شد، اما در اینجا از یک نسخه کمی بهبود یافته استفاده شده است:

پاسخ () (در حین خواندن پاسخ، پاسخ حالت $ را در |) printf "$ 1n" بازگشت 0 break ;; |) printf "$ 2n" بازگشت 1 شکست ;; *) printf "لطفا، Y (بله) یا N (خیر) را وارد کنید!" esac انجام شد)

در اینجا می‌توانید از هر دو while و while استفاده کنید - اما نه از یک حلقه for، زیرا for یک بار کار می‌کرد (PID را دریافت کرد و به پایان رسید).

پوسته bash از حلقه‌ها پشتیبانی می‌کند، که به شما امکان می‌دهد روی دنباله‌ای از مقادیر تکرار کنید. این ساختار اصلی چنین حلقه هایی است:

برای var در لیست دستورات را انجام دهید
در هر تکرار از حلقه، مقدار بعدی از لیست روی متغیر var نوشته می شود. بنابراین در اولین گذر حلقه از اولین مقدار از لیست استفاده خواهد شد. در دوم - دوم و غیره - تا زمانی که چرخه به آخرین عنصر برسد.

تکرار بر روی مقادیر ساده

شاید ساده‌ترین مثال حلقه for در اسکریپت‌های bash تکرار بر روی فهرستی از مقادیر ساده باشد:

#! / bin / bash برای var در اول دوم سوم چهارم پنجم do echo مورد $ var انجام شد
نتایج این اسکریپت در زیر نشان داده شده است. به وضوح مشاهده می شود که عناصر لیست به صورت متوالی در متغیر $ var وارد می شوند. این اتفاق می افتد تا زمانی که چرخه به آخرین آنها برسد.


ساده برای حلقه

لطفا توجه داشته باشید که متغیر $ var ارزش خود را هنگام خروج از حلقه حفظ می کند، محتویات آن قابل تغییر است، به طور کلی، می توانید مانند هر متغیر دیگری با آن کار کنید.

تکرار بر روی مقادیر پیچیده

لیستی که برای مقداردهی اولیه حلقه for استفاده می شود می تواند نه تنها شامل رشته های ساده متشکل از یک کلمه، بلکه عبارات کامل نیز باشد که شامل چندین کلمه و علائم نگارشی است. برای مثال، ممکن است همه چیز به این صورت باشد:

#! / bin / bash برای var در ابتدا "دومین" "سوم" "I'll do it" echo "این است: $ var" انجام شد
این چیزی است که پس از اینکه این حلقه از لیست عبور می کند اتفاق می افتد. همانطور که می بینید، نتیجه کاملاً قابل انتظار است.


تکرار بر روی مقادیر پیچیده
TNW-CUS-FMP - یک کد تبلیغاتی برای 10٪ تخفیف در خدمات ما، برای فعال سازی ظرف 7 روز در دسترس است.

راه اندازی حلقه با لیستی که از نتایج فرمان بدست می آید

راه دیگر برای مقداردهی اولیه یک حلقه for این است که به آن لیستی ارسال کنید که نتیجه یک دستور است. اینجاست که از جایگزینی دستور برای اجرای آنها و دریافت نتایج کارشان استفاده می شود.

#! / bin / bash file = "myfile" برای var در $ (فایل cat $) echo "$ var" انجام شد
این مثال از دستور cat برای خواندن محتویات یک فایل استفاده می کند. لیست مقادیر به دست آمده به حلقه منتقل شده و نمایش داده می شود. لطفاً توجه داشته باشید که فایل مورد نظر ما حاوی لیستی از کلمات است که با کاراکترهای فید خط از هم جدا شده اند و از فاصله استفاده نشده است.


حلقه ای که از طریق محتویات فایل حلقه می زند

باید در نظر داشت که چنین رویکردی، اگر پردازش خط به خط داده ها مورد انتظار باشد، برای فایلی با ساختار پیچیده تر، که خطوط آن ممکن است حاوی چندین کلمه باشد که با فاصله از هم جدا شده اند، کارساز نخواهد بود. حلقه تک تک کلمات را پردازش می کند نه خطوط.

اگر اصلاً آن چیزی نباشد که شما می خواهید چه؟

جداکننده های میدان

دلیل ویژگی فوق در یک متغیر محیطی خاص به نام IFS (جداکننده میدان داخلی) نهفته است که به شما امکان می دهد جداکننده های میدان را مشخص کنید. به طور پیش فرض، bash با کاراکترهای زیر به عنوان جداکننده فیلد رفتار می کند:
  • فضا
  • کاراکتر برگه
  • کاراکتر فید خط
اگر bash با هر یک از این کاراکترها در داده ها روبرو شود، فرض می کند که مقدار مستقل بعدی در لیست جلوی آن است.

برای حل مشکل، می توانید به طور موقت متغیر محیطی IFS را تغییر دهید. در اینجا نحوه انجام آن در یک اسکریپت bash آمده است، با این فرض که فقط به یک خط جدید به عنوان جداکننده فیلد نیاز دارید:

IFS = $ "\ n"
پس از افزودن این دستور به یک اسکریپت bash، همانطور که انتظار می رود کار می کند، فضاها و برگه ها را نادیده می گیرد و فقط فیدهای خط را به عنوان جداکننده فیلد در نظر می گیرد.

#! / bin / فایل bash = "/ etc / passwd" IFS = $ "\ n" برای var در $ (فایل cat $) تکرار "$ var" انجام شد
اگر این اسکریپت را اجرا کنید، دقیقا همان چیزی را که از آن خواسته شده است، خروجی می دهد و در هر تکرار حلقه، به خط بعدی که روی فایل نوشته شده است دسترسی پیدا می کند.


خزیدن یک فایل خط به خط در یک حلقه for

کاراکترهای دیگر را می توان به عنوان جداکننده استفاده کرد. به عنوان مثال، در بالا محتویات فایل / etc / passwd را نمایش دادیم. داده های کاربر در رشته ها با دو نقطه از هم جدا می شوند. اگر نیاز به پردازش چنین خطوطی در یک حلقه دارید، IFS را می توان به صورت زیر پیکربندی کرد:

دور زدن فایل های موجود در یک دایرکتوری

یکی از رایج‌ترین کاربردهای حلقه‌های for در اسکریپت‌های bash، عبور از فایل‌ها در یک فهرست و پردازش آن فایل‌ها است.

به عنوان مثال، در اینجا نحوه فهرست کردن فایل ها و پوشه ها آمده است:

#! / bin / bash برای فایل در / خانه / likegeeks / * اگر [-d "$ file"] انجام دهید، سپس "$ file is a directory" elif [-f "$ file"] سپس "$ file is a فایل "فی انجام شد
اگر از این سری مقالات متوجه شدید، باید ساختار if-then construct و همچنین نحوه تشخیص یک فایل از یک پوشه را بدانید. اگر درک کد بالا برایتان دشوار است، لطفاً این مطالب را دوباره بخوانید.

این همان چیزی است که اسکریپت خروجی خواهد داد.


خروجی گرفتن از محتویات یک پوشه

توجه کنید که چگونه حلقه را مقداردهی اولیه می کنیم، یعنی علامت "*" در انتهای آدرس پوشه. این نماد را می توان به عنوان یک الگو در نظر گرفت، به این معنی: "همه فایل ها با هر نام". این به شما امکان می دهد تا جایگزینی خودکار نام فایل هایی را که با الگو مطابقت دارند سازماندهی کنید.

هنگامی که یک شرط را در یک دستور if آزمایش می کنیم، نام متغیر را داخل علامت نقل قول قرار می دهیم. این کار به این دلیل انجام می شود که نام یک فایل یا پوشه ممکن است حاوی فاصله باشد.

سبک C برای حلقه ها

اگر با زبان برنامه نویسی C آشنایی دارید، سینتکس برای توصیف bash برای حلقه ها ممکن است برای شما عجیب باشد، زیرا واضح است که شما به چنین توصیفی از حلقه ها عادت دارید:

برای (i = 0; i< 10; i++) { printf("number is %d\n", i); }
در اسکریپت‌های bash، می‌توانید از حلقه‌هایی استفاده کنید که شرح آن‌ها بسیار شبیه به حلقه‌های سبک C است، اگرچه در اینجا تفاوت‌هایی وجود دارد. نمودار حلقه با رویکردی مشابه به این صورت است:

برای ((مقدار اولیه متغیر؛ شرط پایان حلقه؛ تغییر متغیر))
در bash می توان آن را اینگونه نوشت:

برای ((a = 1; a< 10; a++))
و در اینجا یک نمونه کار وجود دارد:

#! / bin / bash برای ((i = 1; i<= 10; i++)) do echo "number is $i" done
این کد لیستی از اعداد 1 تا 10 را چاپ می کند.

حلقه زدن به سبک C

در حالی که حلقه

بند for تنها راه برای سازماندهی حلقه ها در اسکریپت های bash نیست. همچنین می توانید از حلقه های while در اینجا استفاده کنید. در چنین حلقه‌ای، می‌توانید دستوری را برای بررسی یک شرایط خاص تنظیم کنید و بدنه حلقه را تا زمانی که شرط بررسی شده صفر شود، یا سیگنالی از اتمام موفقیت‌آمیز یک عملیات خاص، اجرا کنید. وقتی شرط حلقه یک مقدار غیر صفر را برمی گرداند که به معنای خطا است، حلقه متوقف می شود.

در اینجا نموداری از نحوه سازماندهی حلقه های while آورده شده است.
دستور while check condition
انجام دادن
تیم های دیگر
انجام شده

بیایید نگاهی به یک نمونه اسکریپت با چنین حلقه ای بیندازیم:

#! / bin / bash var1 = 5 در حالی که [$ var1 -gt 0] echo $ var1 var1 = $ [$ var1 - 1] انجام شد
در ورودی حلقه بررسی می شود که آیا متغیر $ var1 بزرگتر از صفر است یا خیر. اگر چنین است، بدنه حلقه اجرا می شود که در آن یک از مقدار متغیر کم می شود. این در هر تکرار اتفاق می افتد، در حالی که قبل از تغییر مقدار متغیر را در کنسول چاپ می کنیم. به محض اینکه $ var1 0 شد، حلقه به پایان می رسد.

نتیجه حلقه while

اگر متغیر $ var1 را تغییر ندهید، این منجر به سقوط اسکریپت در یک حلقه بی نهایت می شود.

حلقه های تو در تو

هر فرمانی را می توان در بدنه حلقه استفاده کرد، از جمله راه اندازی حلقه های دیگر. چنین ساختارهایی حلقه های تودرتو نامیده می شوند:

#! / bin / bash برای ((a = 1; a<= 3; a++)) do echo "Start $a:" for ((b = 1; b <= 3; b++)) do echo " Inner loop: $b" done done
در زیر آنچه را که این اسکریپت خروجی می دهد آورده شده است. همانطور که می بینید ابتدا اولین تکرار حلقه بیرونی انجام می شود سپس سه بار تکرار حلقه داخلی که پس از اتمام آن دوباره حلقه بیرونی و سپس دوباره حلقه داخلی وارد بازی می شود.

حلقه های تو در تو

پردازش محتوای فایل

رایج ترین استفاده از حلقه های تو در تو، پردازش فایل ها است. بنابراین، حلقه بیرونی مشغول تکرار روی خطوط فایل است، در حالی که حلقه داخلی در حال حاضر با هر خط کار می کند. به عنوان مثال، پردازش فایل / etc / passwd به این صورت است:

#! / bin / bash IFS = $ "\ n" برای ورود به $ (cat / etc / passwd) echo "مقادیر در ورود $ -" IFS =: برای مقدار در ورودی $، "$ value" را اکو انجام دهید انجام شده
دو حلقه در این اسکریپت وجود دارد. اولین مورد از طریق خطوط با استفاده از کاراکتر تغذیه خط به عنوان جداکننده حلقه می شود. درونی مشغول تجزیه رشته‌هایی است که فیلدهای آن با دو نقطه از هم جدا شده‌اند.

پردازش داده های فایل

این رویکرد می تواند هنگام پردازش فایل های CSV، یا هر فایل مشابه، با نوشتن یک کاراکتر جداکننده در متغیر محیطی IFS در صورت نیاز استفاده شود.

کنترل چرخه

شاید پس از ورود به حلقه، زمانی که متغیر حلقه به مقدار معینی رسید، متوقف شود که با شرایط اولیه مشخص شده برای انتهای حلقه مطابقت ندارد. آیا در چنین شرایطی باید منتظر تکمیل عادی چرخه باشیم؟ البته نه، و در چنین مواردی دو دستور زیر به کار می آیند:
  • زنگ تفريح
  • ادامه هید

دستور شکستن

این دستور به شما اجازه می دهد تا اجرای حلقه را قطع کنید. می توان آن را هم برای حلقه ها و هم برای حلقه های while استفاده کرد:

#! / bin / bash برای var1 در 1 2 3 4 5 6 7 8 9 10 انجام دهید اگر [$ var1 -eq 5] سپس echo fi "Number: $ var1" انجام شد
چنین حلقه ای، در شرایط عادی، کل لیست مقادیر موجود در لیست را طی می کند. با این حال، در مورد ما، زمانی که متغیر $ var1 برابر با 5 شود، اجرای آن قطع خواهد شد.

زودتر از حلقه for خارج شوید

در اینجا همان چیزی برای حلقه while وجود دارد:

#! / bin / bash var1 = 1 در حالی که [$ var1 -lt 10] اگر [$ var1 -eq 5] را انجام دهید، بازتاب fi "تکرار: $ var1" var1 = $ (($ var1 + 1)) انجام شد
دستور break که زمانی اجرا می شود که مقدار $ var1 برابر با 5 باشد، حلقه را می شکند. خروجی کنسول همانند مثال قبلی خواهد بود.

دستور را ادامه دهید

هنگامی که این دستور در بدنه حلقه مواجه می شود، تکرار فعلی زودتر به پایان می رسد و بعدی شروع می شود و حلقه خارج نمی شود. بیایید نگاهی به دستور continue در حلقه for بیندازیم:

#! / bin / bash برای ((var1 = 1; var1< 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
هنگامی که شرط داخل حلقه برآورده شد، یعنی زمانی که $ var1 بزرگتر از 5 و کمتر از 10 باشد، پوسته دستور continue را اجرا می کند. این منجر به پرش از دستورات باقی مانده در بدنه حلقه و ادامه به تکرار بعدی می شود.

دستور ادامه در یک حلقه for

خروجی پردازش در یک حلقه اجرا می شود

داده های خروجی از حلقه را می توان با تغییر مسیر خروجی یا لوله گذاری آن پردازش کرد. این کار با افزودن دستورات پردازش خروجی پس از دستور done انجام می شود.

به عنوان مثال، به جای نشان دادن آنچه در یک حلقه نمایش داده می شود، می توانید همه آن را در یک فایل بنویسید یا آن را به جای دیگری انتقال دهید:

#! / bin / bash برای ((a = 1; a< 10; a++)) do echo "Number is $a" done >myfile.txt اکو "تمام شد."
wrapper فایل myfile.txt را ایجاد می کند و خروجی ساختار for را به آن فایل هدایت می کند. بیایید فایل را باز کنیم و مطمئن شویم که دقیقاً حاوی آن چیزی است که انتظار می رود.

تغییر مسیر خروجی یک حلقه به یک فایل

مثال: جستجوی فایل های اجرایی

بیایید از مطالبی که تاکنون به آن پرداختیم استفاده کنیم و چیز مفیدی بنویسیم. به عنوان مثال، اگر نیاز دارید که بدانید کدام فایل های اجرایی در سیستم موجود است، می توانید تمام پوشه های نوشته شده در متغیر محیطی PATH را اسکن کنید. ما در حال حاضر کل زرادخانه ابزار مورد نیاز خود را برای این کار در اختیار داریم، فقط باید همه آنها را کنار هم بگذاریم:

#! / bin / bash IFS =: برای پوشه در $ PATH echo "$ folder:" را برای فایل در پوشه $ / * اگر [-x $ file] انجام دهید، سپس "$ file" را اکو انجام دهید و تمام شد
چنین اسکریپتی، کوچک و بدون پیچیدگی، امکان دریافت لیستی از فایل های اجرایی ذخیره شده در پوشه ها را از PATH فراهم کرد.

فایل های اجرایی را در پوشه ها از متغیر PATH جستجو کنید

عواقب

امروز در مورد حلقه‌های for و while در اسکریپت‌های bash، نحوه اجرای آنها، نحوه مدیریت آنها صحبت کردیم. اکنون می‌توانید رشته‌ها را با جداکننده‌های مختلف در حلقه‌ها پردازش کنید، می‌دانید چگونه خروجی داده‌ها را در حلقه‌ها به فایل‌ها هدایت کنید، چگونه محتویات دایرکتوری‌ها را مشاهده و تجزیه و تحلیل کنید.

با فرض اینکه شما یک توسعه‌دهنده اسکریپت bash هستید که فقط از آنچه در این سری مقالات توضیح داده شده است می‌دانید، و در این ثانیه، می‌توانید از قبل چیزی مفید بنویسید. قسمت سوم در پیش است که پس از درک آن، یاد خواهید گرفت که چگونه پارامترها و سوئیچ های خط فرمان را به اسکریپت های bash منتقل کنید و با همه اینها چه کاری انجام دهید.

در این سخنرانی در ادامه با هم آشنا می شویم بش... من می خواهم به شما یادآوری کنم که ما در حال بررسی آن عناصر هستیم بشبرای کمک به درک اسکریپت های سیستم عامل. حلقه ها و توابع قطعا چنین عناصری هستند. اگر کسی برنامه نویسی خوانده باشد، در درک این سوالات مشکلی وجود نخواهد داشت.

برای حلقه

چرخه برای v بشدو نوع دارد بیایید ابتدا نسخه کلاسیک را در نظر بگیریم برای... نمای کلی به شرح زیر است:

بین عناصر برایو که دریک متغیر تنظیم می شود که به نوبه خود مقداری را از دنباله ای از مقادیر مشخص شده بین آن می گیرد که درو انجام دادن... بین انجام دادنو انجام شدهدستوراتی وجود دارد که هر بار که یک متغیر مقدار خود را تغییر می دهد، اجرا می شود. زمانی که متغیر آخرین مقدار را از دنباله بگیرد، حلقه اجرا نمی شود. مقادیر موجود در دنباله با یک فاصله از هم جدا می شوند.

و در اینجا یک مثال عملی وجود دارد:

توالی مقادیر را می توان به روش های مختلفی مشخص کرد. به طور واضح - مانند مثال بالا، یا استفاده از متغیرهای دیگر، یا استفاده از دستورات خاص. بیایید به چند نمونه نگاه کنیم. از آنجایی که مقادیر با فاصله از هم جدا شده اند، چنین مقادیری می تواند هر متغیری باشد که دارای رشته ای با فاصله باشد:

نتیجه مانند مثال اول خواهد بود.

اگر نیاز به تعیین دنباله ای از اعداد دارید، می توانید از دستور استفاده کنید دنبالهو مکانیسم جایگزینی تیم دنبالهدنباله ای از مقادیر عددی را به صفحه نمایش برمی گرداند. نحو ساده است و از مثال زیر مشخص خواهد شد:

نتیجه:

به نوع دوم برگردیم برای... اغلب در اسکریپت ها می توانید نوع به اصطلاح C-like را پیدا کنید برایکه برای حلقه های عددی استفاده می شود. بیایید بلافاصله یک مثال را در نظر بگیریم:

حلقه تا زمانی اجرا می شود که شرط بررسی شده در عبارت درست باشد. به محض اینکه عبارت false را برگرداند، اجرای حلقه خاتمه می یابد.

مثال عملی:

#! / bin / bash
i = 1
در حالی که [$ i -lt 7]
انجام دادن
اکو $ i
اجازه دهید i = i + 1
انجام شده

در مثال ما، بررسی می شود که متغیر منکمتر (-lt)، عدد 7 و اگر چنین است، مقدار متغیر نمایش داده می شود. اصطلاح اجازه دهید i = i + 1، متغیر را یک بار افزایش می دهد، دوباره بررسی می کند و غیره. let به مفسر می گوید که با آرگومان ها به عنوان مقادیر عددی برخورد کند. این خط می تواند به صورت نوشته شود اجازه دهید من ++ کنم(گزینه c-like). با افزایش بیش از یک عدد، می توانید آن را به صورت زیر بنویسید: اجازه دهید i + = 2 باشد- در این مورد منبا افزایش 2 افزایش می یابد. گزینه دیگر برای افزایش یک متغیر استفاده از ماشین حساب داخلی است (فقط با اعداد صحیح کار می کند). از طریق دو براکت می توان به ماشین حساب دسترسی داشت: i = $ (($ i + 1))یا از طریق مربع ها: i = $ [$ i + 1]همچنین می توانید از ماشین حساب در خط فرمان استفاده کنید:

با حلقه ها، باید مراقب باشید که گزینه یک حلقه بی نهایت را دریافت نکنید. در ضمن برای رفع اشکال بشاسکریپت ها، می توانید خط اول را به تغییر دهید #! / bin / bash -xیا اسکریپت را با دستور اجرا کنید bash -x:

[ایمیل محافظت شده]: ~ / لینوکس $ bash -x ./testfor.sh
+ i = 1
+ '[' 1 -gt 5']'
+ پژواک i = 1
i = 1
+ اجازه دهید i = i + 1
+ '[' 2 -gt 5 ']'
+ پژواک i = 2
i = 2
+ اجازه دهید i = i + 1
+ '[' 3 -gt 5 ']'
+ پژواک i = 3
i = 3
+ اجازه دهید i = i + 1
+ '[' 4 -gt 5 ']'
+ پژواک i = 4
من = 4
+ اجازه دهید i = i + 1
+ "[" 5 -gt 5 "]"
+ پژواک i = 5
من = 5
+ اجازه دهید i = i + 1
+ '[' 6 -gt 5 ']'

حتماً نوشتن اسکریپت های کوچک را تمرین کنید تا درک خود را از نحوه عملکرد حلقه ها تقویت کنید بش.

توابع در bash

توابع در اعمال می شوند بشخیلی عریض. توابع به دو صورت توصیف می شوند: با کلمه کلیدی عملکرد، و بدون آن.

راه اول:

تابع function_name
{
بدن عملکرد
}

راه دوم:

function_name ()
{
بدن عملکرد
}

تابع با نام در هر نقطه از اسکریپت فراخوانی می شود، اما فقط پس از شرح خود تابع. همچنین می توانید پارامترهایی را به توابع ارسال کنید که با فاصله بعد از فراخوانی (نام) تابع مشخص می شوند. بیایید یک نمونه اسکریپت را در نظر بگیریم بش:

#! / bin / bash
پرایمر عملکردی
{
اگر [$ # -ne 0]
سپس
محلی a = 1
echo "تعداد پارامترهای ارسال شده - $ #"
برای من در [ایمیل محافظت شده]
انجام دادن
echo "$ a-امین پارامتر $ i است"
یک ++ بگذارید
انجام شده
بازگشت 0
دیگر
echo "هیچ پارامتری ارسال نشد"
بازگشت 1
فی
}
echo " فراخوانی تابع با پارامترها:"
آغازگر a b c
اکو $؟
echo " فراخوانی تابع بدون پارامتر:"
آغازگر
اکو $؟

در این مثال، تابعی به نام آغازگر... فراخوانی تابع با پارامترها: آغازگر a b cو بدون پارامتر: آغازگر... در بدنه تابع، تمام ساختارها باید برای شما آشنا باشند، به استثنای $# , $ iو [ایمیل محافظت شده] .$# - تعداد پارامترهای ارسال شده به تابع را برمی گرداند. در مثال ما، این عدد خواهد بود 3 .[ایمیل محافظت شده] تمام پارامترها را در یک خط برمی گرداند. در مثال این خواهد بود a b c... و بعد از $1 , $2 , $3 و غیره. شما می توانید به هر پارامتر شخصا رسیدگی کنید. $? - حاوی کد اجرای آخرین دستور است. در مثال ما، کد اجرای تابع.

این تابع همچنین می تواند یک مقدار عددی را از طریق یک کلمه کلیدی برگرداند برگشت... به عنوان یک قاعده، اگر تابع بدون خطا اجرا شد، 0 یا اگر مشکلی پیش آمد، مقدار غیر صفر را برمی‌گردانند. در مثال، اگر تابعی با پارامتر فراخوانی شود، مقدار 0 برگردانده می شود و اگر تابع بدون پارامتر فراخوانی شده باشد، کد 1 برگردانده می شود.

همه چیز در مورد ارسال پارامترها به یک تابع برای یک اسکریپت یکسان است. اسکریپت همچنین می‌تواند پارامترها را به همان روش ارسال کند و آنها را به همان روش با استفاده از دستکاری کند $#, [ایمیل محافظت شده]، N $... از همان دسته و گزینه - $0 - که نام دستوری را که اسکریپت را راه اندازی کرده است برمی گرداند. اگر اسکریپت توسط دستور اجرا می شد ./script.shسپس اکو $0 مقدار را برمی گرداند ./script.sh، و اگر به دستور باشد /home/igor/linux/script.shسپس مقدار برگردانده خواهد شد /home/igor/linux/script.sh.