خط فرمان لینوکس

ترجمه فارسی LinuxCommand.org

خط فرمان لینوکس

ترجمه فارسی LinuxCommand.org

کنترل جریان - بخش 2

کنترل جریان - بخش 2

آماده باشید غافلگیر نشوید. این درس، درس سنگینی خواهد بود!

انشعاب بیشتر

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

یک نوعِ دوم و پیچیده‌تر از انشعاب به نام case وجود دارد. یک case انشعاب چند شاخه است. بر خلاف انشعاب ساده که در آن شما یکی از دو مسیر ممکن را انتخاب می‌کنید، یک case چندین پیامد محتمل بر اساس ارزیابی یک کمیت را پشتیبانی می‌کند.

شما می‌توانید این نوع انشعاب را با چندین جمله if طرح‌ریزی کنید. در مثال پایین، ما ورودی کاربر را ارزیابی می‌کنیم:

#!/bin/bash

echo -n "Enter a number between 1 and 3 inclusive > "
read character
if [ "$character" = "1" ]; then
    echo "You entered one."
elif [ "$character" = "2" ]; then
    echo "You entered two."
elif [ "$character" = "3" ]; then
    echo "You entered three."
else
    echo "You did not enter a number between 1 and 3."
fi

خیلی دلچسب نیست.

خوشبختانه، پوسته یک راه‌حل بیشتر برازنده برای این مورد فراهم می‌کند. فرمان داخلی به نام case را فراهم می‌کند، که در آن می‌توانید یک برنامه هم‌ارز برنامه فوق بسازید:

#!/bin/bash

echo -n "Enter a number between 1 and 3 inclusive > "
read character
case $character in
    1 ) echo "You entered one."
        ;;
    2 ) echo "You entered two."
        ;;
    3 ) echo "You entered three."
        ;;
    * ) echo "You did not enter a number between 1 and 3."
esac

فرمان case دارای قالب زیر است:

case word in
    patterns ) commands ;;
esac

case به طور انتخابی جملات را در صورتیکه word با یک pattern مطابقت کند اجرا می‌کند. می‌توانید هر تعداد الگو (pattern) و جمله داشته باشید. الگوها می‌توانند متن لفظی یا کاراکتر عام باشند. می‌توانید الگوهای چندگانه که با کاراکتر ‎"|"‎ جدا گردیده‌اند داشته باشید. در اینجا یک مثال برای نشان دادن آنکه منظورم چیست:

#!/bin/bash

echo -n "Type a digit or a letter > "
read character
case $character in
                                # بررسی برای حروف‎
    [[:lower:]] | [[:upper:]] ) echo "You typed the letter $character"
                                ;;

                                # بررسی برای ارقام‎
    [0-9] )                     echo "You typed the digit $character"
                                ;;

                                # بررسی هر مورد دیگر‎
    * )                         echo "You did not type a letter or a digit"
esac

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

حلقه‌ها

آخرین نوع کنترل جریان برنامه که ما گفتگو خواهیم نمود حلقه‌زنی نامیده می‌شود. حلقه‌زنی اجرای تکرار شونده یک بخش از برنامه بر اساس وضعیت خروج یک فرمان است. پوسته سه فرمان برای حلقه‌زنی ارایه می‌کند: while، ‏until و for. ما در این درس while و until و در درس آینده for را پوشش می‌دهیم.

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

#!/bin/bash

number=0
while [ "$number" -lt 10 ]; do
    echo "Number = $number"
    number=$((number + 1))
done

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

به کلمه do در سطر چهارم و کلمه done در سطر هفتم توجه کنید. اینها قطعه کدی را که می‌خواهیم تا زمانی که وضعیت خروج صفر باقی بماند تکرار شود محصور می‌کنند.

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

در مثال، قطعه کد تکرار شونده مقدار number را بیرون می‌دهد (فرمان echo در سطر 5) و در سطر ششم number را یک واحد افزایش می‌دهد. هر نوبت که قطعه کد تکمیل می‌گردد، دوباره وضعیت خروج فرمان ‎[‎ ارزیابی می‌شود. بعد از دهمین تکرارِ حلقه، number ده مرتبه افزایش یافته است و فرمان test با وضعیت خروج غیرصفر خاتمه می‌یابد. در آن نقطه، جریان برنامه با جمله بعد از کلمه done ادامه می‌یابد. چون done آخرین سطر مثال ما است، برنامه پایان می‌پذیرد.

فرمان until دقیقاً به همان روش عمل می‌کند، غیر از آنکه، قطعه کد تا وقتی که وضعیت خروج فرمانِ تعیین شده غلط باشد تکرار می‌گردد. در مثال پایین، ملاحظه کنید که چطور عبارت داده شده به فرمان test برای رسیدن به همان نتیجه نسبت به مثال while تغییر کرده است:

#!/bin/bash

number=0
until [ "$number" -ge 10 ]; do
    echo "Number = $number"
    number=$((number + 1))
done 

ساختن یک منو

یک روش رایجِ نمایش یک واسط کاربر برای برنامه‌های بر پایه متن، کاربرد یک منو است. یک منو فهرستی از انتخاب‌ها است که کاربر می‌تواند برگزیند.

در مثال زیر، ما با استفاده از دانش جدید در مورد حلقه‌ها و caseها برای ساختن یک برنامه ساده دارای منو استفاده می‌کنیم:

#!/bin/bash

selection=
until [ "$selection" = "0" ]; do
    echo "
    PROGRAM MENU
    1 - Display free disk space
    2 - Display free memory

    0 - exit program
"
    echo -n "Enter selection: "
    read selection
    echo ""
    case $selection in
        1 ) df ;;
        2 ) free ;;
        0 ) exit ;;
        * ) echo "Please enter 1, 2, or 0"
    esac
done 

در این برنامه مقصود از حلقه until نمایش مجدد منو است، بعد از آن که یک انتخاب تکمیل گردیده باشد. حلقه تا زمانیکه انتخاب برابر ‎"0"‎ یعنی ‎"exit"‎ شود ادامه می‌یابد. ملاحظه کنید چگونه در برابر ورودی‌های کاربر که انتخاب معتبری نیستند دفاع کردیم.

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

#!/bin/bash

press_enter()
{
    echo -en "\nPress Enter to continue"
    read
    clear
}

selection=
until [ "$selection" = "0" ]; do
    echo "
    PROGRAM MENU
    1 - display free disk space
    2 - display free memory

    0 - exit program
"
    echo -n "Enter selection: "
    read selection
    echo ""
    case $selection in
        1 ) df ; press_enter ;;
        2 ) free ; press_enter ;;
        0 ) exit ;;
        * ) echo "Please enter 1, 2, or 0"; press_enter
    esac
done