منبع اصلی نوشتار زیر در این لینک قرار دارد

بررسی حلقه for در bash

در ابتدا فرا رسیدن عید نوروز رو به تمام خوانندگان این وبلاگ تبریک میگم. و سال خوبی رو برای همگی آرزو دارم.

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

  1. حلقه هایی تعداد اجرای آن‌ها مشخص است.
  2. حلقه هایی که تعداد اجرای آن‌ها به درستی مشخص نیست و اجرای حلقه توسط یک شرط کنترل میشود.

For یک نمونه از حلقه نوع اول است. Until و while هم نمونه هایی از حلقه ی نوع دوم هستند. در این ورودی وبلاگ، حلقه for در پوسته bash را بررسی میکنیم. Bash پوسته پیشفرض در اکثر توزیعهای لینوکس است.

خب همانطور که گفتیم تعدادِ تکرار در حلقه for مشخص است. مثلاً میگوییم فلان خط را ۵ بار اجرا کن. برای حلقه for ما نیاز به یک متغیر داریم که تعداد تکرار را شمارش کند. به این متغیر شمارنده حلقه میگویند. اولین بار که حلقه اجرا میشود، یک مقدار خاصی به شمارنده حلقه اختصاص می‌یابد . سپس با هر بار اجرای حلقه، مقدار این شمارنده تغییر میکند. به این تغییر، گام حرکتی میگویند. گام حرکتی میتواند افزایشی یا کاهشی باشد. مثلاً مقدار اولیه شمارنده ۱ باشد و هر بار یکی به آن اضافه شود تا زمانیکه مقدار آن به ۱۰ برسد. یا اینکه مقدار اولیه ۱۰ باشد و هر بار دو تا از آن کم شود تا به صفر برسد. (اعداد منفی هم قابل قبول است)

خب کمی با مفاهیم مقدماتی حلقه for آشنا شدیم، بهتر است به سراغ یادگیری syntax آن برویم.

در bash، حلقه for دو شکل دارد. شکل اول به این صورت است:

for VARIABLE in 1 2 3 4 5 .. N
do
        command1
        command2
		.
		.
		.
        commandN
done

VARIABLE نام متغیری است که برای شمارنده حلقه انتخاب میکنیم (قوانین نامگذاری این متغیر، از قوانین نامگذاری متغیرها در پوسته تبعیت میکند) . ۱ ۲ ۳ ۴ ۵ .. N هم مقادیری هستند که با هر بار اجرای حلقه، به این متغیر انتساب داده میشوند.

مثال:

for i in 1 2 3 4 5
do
	echo $i
done

با اجرای قطعه کد بالا، عدد های یک تا پنج چاپ میشوند. البته شما میتوانید به جای این اعداد، هر مقدار دیگری را به متغیر انتساب کنید. یک مثال دیگر میزنیم:

for i in debian ubuntu mint parsix suse
do
	echo $i
done

با اجرای قطعه کد بالا، اسامی تعدادی از توزیعهای لینوکس چاپ میشود.

همانطور که میدانید کاراکتر * در پوسته اسامی تمام فایلهای موجود در دایرکتوری جاری را برمیگرداند. مثلاً اگر تایپ کنید echo * لیست فایلهای موجود در دایرکتوری جاری نمایش میابد. حالا شما به عنوان تمرین، برنامه‌ای با حلقه for بنویسید که لیست تمام فایهای موجود در دایرکتوری جاری را چاپ کند.

اگر بخواهید اسکریپتی بنویسید که عدد های ۱ تا ۱۰۰۰ را چاپ کند، چکار میکنید؟ یکی از راهها این است که در قسمت مقادیر، عدد های ۱ تا ۱۰۰۰ را به ترتیب بنویسید. اما این کار زمان و انرژی زیادی را طلب میکند و اصلاً عاقلانه نیست. بیاد داشته باشید که هر چقدر برنامه نویس ماهر تری باشید، تنبل تر خواهید بود. تنبلی در برنامه نویسی چیز خوبی است! خوشبختانه bash یک راهکار سریع فراهم کرده. به مثال زیر توجه کنید:

for i in {1..1000}
do
	echo $i
done

به همین راحتی! البته نسخه های قدیمی تر bash این قابلیت را ندارند.

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

for i in {0..1000..2}
do
	echo $i
done

برای به خاطر سپردن سینتکس، عبارت زیر را بیاد داشته باشید:

{START..END..INCREMENT}

دستور seq

دستور seq برای چاپ کردن دنباله ای از اعداد مورد استفاده قرار میگیرد. اگر از نسخه های قدیمی bash استفاده میکنید، میتوانید برای کنترل شمارنده از این دستور کمک بگیرید. در اینجا ما فقط به عنوان یک مثال آموزشی از این دستور استفاده میکنیم. اما شما سعی کنید تا از این دستور برای کنترل شمارنده استفاده نکنید. چون نسبت به دستور داخلی {STAR..END} سرعت کمتری دارد. به هر حال بد نیست کمی با این دستور آشنا شویم.

سینتکس آن به شکل زیر است:

seq [OPTION]... LAST

seq [OPTION]... FIRST LAST

seq [OPTION]... FIRST INCREMENT LAST

مثال:

seq 100
seq 100 200
seq 2 2 100

دستور اول اعداد ۱ تا ۱۰۰ را چاپ میکند. دستور دوم اعداد ۱۰۰ تا ۲۰۰ را چاپ میکند و دستور آخر هم اعداد زوج ۲ تا ۱۰۰ را چاپ میکند. به طور پیشفرض هر عدد در یک خط چاپ میشود. یعنی اعداد با کاراکتر \\n از یکدیگر جدا میشوند. میتوانید برای جدا کردن اعداد از هر کاراکتر دلخواهی استفاده کنید. گزینه -s برای این کار مهیا شده است.

Seq -s \' \' 100

در مثال بالا، اعداد با کاراکتر space از یکدیگر جدا میشوند.

ترکیب seq با for

مثال زیر اعداد فرد ۱ تا ۵۰ را چاپ میکند.

for i in $(seq 1 2 50)
do
	echo $i
done

شکل دوم از حلقه for

اگر برنامه نویس C هستید، شکل دوم حلقه for برایتان بسیار ساده خواهد بود:

for  (( INITIALIZATION; CONDITION; STEP))
do
	command1
	command2
	.
	.
	.
	commanN
done

مطالبی که در ابتدای مقاله ذکر شد، بیشتر به درد شکل دوم حلقه for میخورند. قسمت INITIALIZATION همان مقدار اولیه شمارنده حلقه است. CONDITION شرط ادامه حلقه و STEP گام حرکتی است. یک مثال ساده:

for (( i=0; $i<=100; i=$i+1))
do
	echo $i
done

برنامه را اجرا کنید تا خروجی آن را ببینید.

البته شکل زیر هم صحیح است:

for ((i=0; i<=100; i++))
do
	echo$i
done

اگر برنامه نویس c باشید، احتمالاً شکل دوم برایتان آسانتر خواهد بود.

حلقه بینهایت

در مثال زیر ما نه شمارنده داریم، نه شرط و نه گام حرکتی. پس حلقه بینهایت بار اجرا میشود:

for(( ; ; ))
do
	echo “Press Control-C to Break”
done

حلقه با چند شمارنده

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

for (( i=0,j=10;i<=10,j>=0;i=$i+1,j=$j-1))
do
	echo -e “$i \\t $j”
done

تمرین: فرض کنید در یک دایرکتوری چند فایل با اسامی زیر داریم:

$ ls

BAR  BARBAZ  BAZ  FOO  FOOBAR  FOOBAZ

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

راهنمایی: در مورد دستور tr تحقیق کنید.

در صورت امکان برنامه را در قسمت نظرهای همین پست بنویسید.



برچسب ها : , ,