چه چیز یک متغیر را محلی میسازد؟
متغیر تعریف شده به صورت محلی، متغیری است که فقط در درون بلوک کدی که در آن ظاهر میشود قابل دیدن است. این متغیر دارای حوزه محلی است. در یک تابع، متغیر محلی فقط در درون بلوک آن تابع معنا دارد. [1]
مثال 24-12. پیدایی متغیر محلی
#!/bin/bash #متغیرهای محلی و سراسری داخل یک تابع. func () { local loc_var=23 #به عنوان متغیر محلی تعریف شده. echo #از فرمان داخلی local استفاده میشود. echo "\"loc_var\" in function = $loc_var" global_var=999 #به عنوان محلی تعریف نگردیده است. #بنابراین به طور پیشفرض سراسری میشود. echo "\"global_var\" in function = $global_var" } func #اکنون، دیدن آنکه آیا متغیر محلی loc_var خارج از تابع وجود دارد. echo echo "\"loc_var\" outside function = $loc_var" # #خیر، loc_var به طور سراسری قابل دیدن نیست. echo "\"global_var\" outside function = $global_var" # #global_var به طور سراسری قابل دیدن است. echo exit 0 #در مقایسه با C، یک متغیر Bash تعریف شده داخل یک تابع فقط موقعی #+محلی است که به همین صورت (محلی) تعریف بشود.
قبل از اینکه تابعی فراخوانی بشود، تمام متغیرهای تعریف شده داخل تابع، در خارج از بدنه تابع ناپیدا هستند، نه فقط آنهایی که به طور صریح محلی تعریف شدهاند. #!/bin/bash func () { global_var=37 # |
به طوریکه Evgeniy Ivanov توضیح میدهد، موقع تعریف نمودن و تنظیم کردن متغیر محلی در یک فرمان منفرد، ظاهراً ترتیب عملیات به این صورت است که اول تنظیم متغیر، و فقط پس از آن محدود نمودنش به حوزه محلی انجام میشود. این مورد در مقدار برگشتی منعکس میگردد. #!/bin/bash echo "==OUTSIDE Function (global)==" t=$(exit 1) echo $? # |
بازگشت، یک شکل جالب و گاهی اوقات مفید از خود ارجاعی است. Herbert Mayer آن را به عنوان «. . . بیان یک الگوریتم با استفاده از نگارش سادهتری از همان الگوریتم . . .»تعریف میکند تعریف تعریف شده برحسب خودش [2]، یک اصطلاح که به طور ضمنی در خود اصطلاح فهمانده شده [3]، یک مار در حال بلعیدن دم خودش [4]، یا . . . تابعی که خودش را فراخوانی میکند[5] در نظر بگیرید. مثال 24-13. نمایش تجربی یک تابع بازگشتی ساده #!/bin/bash # # مثال 24-14. یک نمایش تجربی ساده دیگر #!/bin/bash # # |
متغیرهای محلی ابزار مفیدی برای نوشتن کد بازگشتی هستند، اما به طور کلی این شیوه، پردازش محاسباتی بسیار زیادی را در بر میگیرد و به طور قطع در یک اسکریپت پوسته پیشنهاد نمیشود. [6]
مثال 24-15. بازگشت، با استفاده از یک متغیر محلی
#!/bin/bash #فاکتوریل #--------- #آیا bash بازگشت را اجازه میدهد؟ #خب، بله، اما... چنان آهسته است که باید مخ #شما تاب داشته باشد تا آن را به کار ببرید. MAX_ARG=5 E_WRONG_ARGS=85 E_RANGE_ERR=86 if [ -z "$1" ] then echo "Usage: `basename $0` number" exit $E_WRONG_ARGS fi if [ "$1" -gt $MAX_ARG ] then echo "Out of range ($MAX_ARG is maximum)." #اکنون اجازه بدهید واقعبین باشیم. #اگر محدودهای بزرگتر از این میخواهید، آن را #+در یک زبان برنامهنویسی واقعی بازنویسی کنید. exit $E_RANGE_ERR fi fact () { local number=$1 #متغیر number باید به صورت محلی تعریف شده #+باشد، در غیر اینصورت، این کار نمیکند. if [ "$number" -eq 0 ] then factorial=1 #فاکتوریل صفر مساوی یک است. else let "decrnum = number - 1" fact $decrnum #فراخوانی تابع بازگشتی (تابع خودش را احضار میکند). let "factorial = $number * $?" fi return $factorial } fact $1 echo "Factorial of $1 is $?." exit 0
همچنین برای مثالی از بازگشت در یک اسکریپت، مثال A-15 را ببینید. آگاه باشید که بازگشت به شدت منابع سیستم را مصرف میکند و به طور آهسته اجرا میشود، و بنابراین به طور کلی در یک اسکریپت مناسب نیست.
[1] | اما، به طوریکه Thomas Braunberger توضیح میدهد، متغیر محلی تعریف شده در یک تابع، برای توابع فراخوانی شده توسط آن تابع نیز قابل دیدن است. #!/bin/bash function1 () { local func1var=20 echo "Within function1, \$func1var = $func1var." function2 } function2 () { echo "Within function2, \$func1var = $func1var." } function1 exit 0 # این مطلب در راهنمای Bash مستند گردیده است: «منطقه فقط در داخل یک تابع میتواند استفاده شود، این باعث میشود نام یک متغیر دارای حوزه قابل رویت محدود شده به آن تابع و فرزندان آن باشد.» [تاکید اضافه شده] نگارنده راهنمای ABS تصور میکند این رفتار یک باگ باشد. |
[2] | به طور دیگر حشو شناخته میشود. |
[3] | به طریقی دیگر همانگویی نامیده میشود. |
[4] | به بیان دیگر یک استعاره گفته میشود. |
[5] | به طور دیگر یک تابع بازگشتی نامیده می شود. |
[6] | تعداد زیاد مراحل بازگشت میتواند باعث از کار افتادن اسکریپت با یک خطای segfault بشود. #!/bin/bash # |