آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

پرسش و پاسخ شماره ۸۳

پرسش و پاسخ شماره ۸۳

چگونه می توانم تعیین کنم که آیا یک متغیر قبلاً تعریف شده است؟

چندین روش بر حسب موارد نیاز، برای بررسی یک متغیر تعریف شده یا غیرتهی یا تابع وجود دارد.

"Declared"، "Defined"، و "Undefined"

همانند بسیاری از زبانها تعیین و تعریف می‌توانند مراحل مستقلی باشند. تعیین(declare) یک شیء، دادن نام و نوع داده به آن است، در جایی که تعریف(definition) آن را با یک مقدار مرتبط می‌کند، که می‌تواند تهی باشد. در واژگان فنی پوسته یونیکس، set، unset، و null به ترتیب به معنی تعریف نشده، تعریف شده، و تهی می‌باشند. چون رشته تقریباً تنها نوع‌داده رایج است، "null" معمولاً به معنی رشته تهی است. در مورد آرایه‌ها، موارد سازگاری بین پوسته‌ها کمتر می‌شود.

بررسی برای پارامتر/متغیر تعریف شده غیرتهی.

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

test x"$var" != x

فقط برای پوسته‌های باستانی Bourne. در اسکریپت‌های مدرن از این استفاده نکنید.

test -n "$var"

‎POSIX sh به اضافه پوسته‌های قدیمی‌تر Bourne که فاقد ‎[‎ هستند.

[ -n "$var" ]

‎POSIX sh‎ و اکثر پوسته‌های Bourne. روی‌هم رفته بهترین انتخاب برای اسکریپت‌های جدید نیازمند سازگاری با POSIX.

test "$var"

‎POSIX sh‎، استاندارد POSIX تصریح می‌کند که غیرتهی همیشه صحیح است در حالیکه تهی همیشه غلط است.

[ "$var" ]

‎POSIX sh‎، مانند مورد فوق بازهم خیلی قابل حمل.

[[ -n $var ]]

این مورد و بعدی فقط در ‎Bash/Ksh/Zsh‎، این با برخی نگارشهای پوسته buggy که گزینه ‎-n‎ صریح را به طور صحیح پردازش نمی‌کنند سازگار است.

[[ $var ]]

به طور کلی در جایی که POSIX مورد نیاز نیست بهترین انتخاب برای Bash و Ksh. به طور معمول دارای بهترین کارایی. در Zsh کار نخواهد کرد.

(( ${#var} ))

تقریباً به اندازه مورد قبل قابل حمل. در واقع همیشه آهسته‌تر. از این مورد برای بررسی رشته‌های تهی استفاده نکنید.

برای بررسی معکوس، آیا یک متغیر تهی است(unset یا به طول صفر)، منطق بالا را برعکس کنید.

test x"$var" = x
test -z "$var"
[ -z "$var" ]
test ! "$var"
[ ! "$var" ]
[[ -z $var ]]
[[ ! $var ]] #      یا هر مورد تقلید شده آن کار نخواهد نمود. اگر چنین Zsh همچنین در 
             #‎‎‏ در این صفحه را تنظیم کنید‏-z‎ یا ‎-n قابلیتی مورد نیاز است، راه حل صریح

بررسی آن که یک متغیر تعیین شده است

تمیز دادن میان متغیری که تعریف‌نشده است و آنکه تعریف‌شده اما تهی است تا اندازه‌ای ماهرانه، اما امکان‌پذیر است.

# POSIX
${var+:} false
! ${var+false}
[ -n "${var+_}" ]
[ "${var+_}" ]

اینکه کدام یک از موارد فوق بهترین اجراست از یک پوسته تا دیگری فرق می‌کند. اگر POSIX مورد نیاز نیست، راه حل ‎[[‎ پایین معمولاً بهترین اجرا می‌باشد.

# Bash/ksh
[[ ${var+_} ]]

شیوه دیگری که گهگاهی دیده شده است، بررسی وضعیت ‎typeset -p‎ است. روش فوق باید بر آن ترجیح داده شود.

# Bash/ksh/zsh
typeset -p var >/dev/null 2>&1
#  موجود باشد صفر را و در غیر آن صورت خطا برمی‌گرداندvar اگر

‎Bash 4.2‎ یک ‎-v test اضافه می‌کند:

# Bash 4.2 / ksh93
if [[ -v var ]]; then echo "var is defined"; fi

ksh93 به طور افزون از شاخص‌های آرایه با ‎-v test‎ پشتیبانی می‌کند، در حالیکه Bash تا به حال پشتیبانی نمی‌کند. وقتی که مقصد به طور خاص ksh93 باشد، باید این شیوه ترجیح داده شود.

بررسی آنکه یک تابع تعریف شده است

برای تعیین آنکه آیا تابعی با نام معین قبلاً تعریف شده است، چند جواب وجود دارد، تمام آنها به فرمانهای Bash (یا حداقل پوسته‌های غیرBourne) نیاز دارند. بررسی آنکه تابعی از قبل تعریف شده است، به ندرت لازم خواهد شد.

typeset -f f >/dev/null        #   Bash/Ksh -    تعریف نشده باشد غلط در غیر آنصورت‎
                               #                                  .صحیح برمی‌گرداند
[[ $(typeset -f f) ]]          #   Bash/Ksh -  در صورتیکه تعریف نشده باشد چیزی چاپ‎
                               # نمی‌کند در غیر آنصورت تعریف تابع را در خروجی می‌دهد
[[ $(type -t f) == function ]] #   اگر تعریف شده باشد تابع را بیرون می‌دهد Bash فقط‎
 #                  است "whence -v" مستعاری برای "type"  فرق می‌کند،(mksh و) ksh در‎

 #    راه عبوری برای مورد فوق دارند اما دو روش اول بیشتر قابل ترجیح هستند Bash/Ksh 
isFunction() [[ $(type ${BASH_VERSION:+-t} "$1") == ${KSH_VERSION:+"$1 is a "}function ]]; isFunction f 

پرسش و پاسخ 83 (آخرین ویرایش ‎2012-11-23 09:57:53‎ توسط ormaaj)