4. بررسیهای Bash
فرمان test که به عنوان [ نیز شناخته شده، یک برنامه کاربردی است که به طور معمول جایی در /usr/bin یا /bin استقرار مییابد و خیلی زیاد توسط برنامهنویس پوسته برای اجرای آزمایشهای معینی با متغیرها و فایلها، به کار میرود. در تعدادی از پوستهها، از جمله Bash, دستور test به صورت دستور داخلی پوسته نیز پیادهسازی گردیده است.
این مورد میتواند نتایج شگفانگیزی فراهم نماید، به ویژه برای آنان که شروع به اسکریپتنویسی پوسته مینمایند و تصور میکنند [ ] بخشی از دستور زبان پوسته است.
اگر از پوسته sh استفاده میکنید، انتخاب کمی دارید و استفاده از test تنها راه انجام اکثر بررسیهایتان میباشد.
گرچه اگر از Bash در اسکریپتنویسی استفاده میکنید(و من فرض میکنم چنین است، چون در حال خواندن این راهنما هستید)، پس میتوانید از کلید واژه [[ نیز استفاده کنید. هر چند بازهم از خیلی جهات همچون یک فرمان رفتار میکند، چندین مزیت نیز نسبت به فرمان سنتی test ارائه میکند.
اجازه بدهید تشریح کنم که چگونه [[ میتواند با فرمان test تعویض شود، وچطور میتواند به شما کمک کند از برخی اشتباهات متداول در کاربرد test پرهیز نمایید:
$ var=''
$ [ $var = '' ] && echo True
-bash: [: =: unary operator expected
$ [ "$var" = '' ] && echo True
True
$ [[ $var = '' ]] && echo True
True
قسمت [ $var = '' ] به [ = '' ] بسط داده میشود. اولین کاری که دستور test انجام میدهد، شمارش شناسههایش میباشد. چون [ را به کار بردهایم، باید شناسه الزامی ] در انتها را کنار بگذاریم. در مثال اول، test دو شناسه میبیند: = و ''. حالا میداند که دو شناسه دارد، اولی باید unary operator (یک عملگر که یک عملوند میگیرد). اما = عملگر یگانی(unary operator) نیست(یک عملگر binary است که دو عملوند نیاز دارد)، بنابراین، test نمیتواند کار کند.
بله، test متغیر تهی $var را نمیبیند، زیرا BASH قبل از اینکه test حتی بتواند آن را ببیند، به هیچ بسطش داده است. نتیجه اخلاقی؟ استفاده بیشتر از نقلقولها! کاربرد نقلقولها در قسمت، [ "$var" = '' ] موجب بسط آن به [ "" = '' ] میگردد و test مشکلی ندارد.
حال آنکه، [[ میتواند تمام دستور را قبل از اینکه بسط داده شود، ببیند. میتواند $var را ببیند، و نه بسط $var را. در نتیجه، نیازی به نقلقولها نمیباشد! [[ مطمئنتر است.
$ var=
$ [ "$var" < a ] && echo True
-bash: a: No such file or directory
$ [ "$var" \< a ] && echo True
True
$ [[ $var < a ]] && echo True
True
در این مثال سعی نمودهایم یک مقایسه رشتهای بین یک متغیر تهی و 'a' انجام بدهیم. شگفتزده میشویم با دیدن آنکه از اولین تلاش ما True حاصل نمیگردد، ولواینکه تصور میکردیم، میشود. درعوض، با خطای عجیبی که دلالت بر تلاش BASH برای باز کردن فایلی به نام 'a' مینماید، مواجه میشویم.
ما توسط تغییر مسیر فایل گَزیده شدهایم. چون test دقیقاً یک برنامه کاربردی است، کاراکتر < در دستور ما به جای عملگر مقایسه رشتهای برای test، به عنوان عملگر تغییر مسیر فایل تفسیر شده است(همانطور که باید میشد). BASH دستور باز کردن فایل 'a' و اتصال آن به stdin برای خواندن را دریافت نموده. برای پیشگیری از این مورد، لازم است, < را با کاراکتر گریز پوشش دهیم، به طوری که به جای BASH برنامه test عملگر را دریافت کند. این دومین تلاش ما را تشکیل داد.
با استفاده از [[ میتوانیم رویهمرفته از نابسامانی اجتناب نماییم. [[ عملگر < را قبل از آنکه BASH آنرا برای تغییر مسیر دریافت کند، میبیند -- مشکل رفع میشود. یکبار دیگر [[ مطمئنتر است.
حتی خطرناکتر، استفاده از عملگر > به جای عملگر < مثال قبلی است. چون > ماشهٔ تغییر مسیر خروجی را میکشد، فایلی به نام'a' ایجاد خواهد نمود. در نتیجه، هیچ پیغام خطای هشداردهندهای برای ما صادر نمیشود که بدانیم مرتکب اشتباه شدهایم! به جای آن، فقط اسکریپت ما خراب میشود. حتی وخیمتر، شاید فایل مهمی را رونویسی کنیم! برای ما حدس زدن آنکه مشکل کجاست، سخت است:
$ var=a
$ [ "$var" > b ] && echo True || echo False
True
$ [[ "$var" > b ]] && echo True || echo False
False
دو نتیجه متفاوت، شگرف. به من اعتماد کنید، وقتی میگویم، همیشه میتوانید به [[ بیشتر از [ اطمینان کنید. [ "$var" > b ] به [ "a" ] بسط یافته و خروجی به یک فایل جدید به نام 'b' تغییر مسیر داده میشود. چون [ "a" ] در واقع همان [ -n "a" ] میباشد و اساساً بررسی میشود که آیا رشته "a" غیرتهی است، نتیجه بررسی موفق است و echo True اجرا میشود.
با کاربرد [[ انتظار ما که مقایسه "a" در برابر "b" است، برآورده میشود، و نظر به اینکه همه میدانیم "a" قبل از "b" مرتب میشود، ماشه اجرای دستور echo False کشیده میشود. و این چگونگی آنست که اسکریپت شما بدون پیبردن شما میتواند ناموفق بشود. هر چند که، شما یک فایل شبهه برانگیزی به نام 'b' نیز در دایرکتوری جاری خواهید داشت.
بنابراین به من باور داشته باشید، وقتی میگویم، [[ مطمئنتر از [ است. زیرا هر کسی به ناچار خطاهای برنامهنویسی را ایجاد میکند. افراد به طور معمول قصد ندارند، باگهایی در کدهایشان ارائه کنند. اما اتفاق میافتد. بنابراین مدعی نشوید که از [ استفاده میکنید و "مراقب خواهید بود که چنین اشتباهاتی مرتکب نگردید"، زیرا میتوانم شما را مجاب کنم که مرتکب خواهید شد.
گذشته ازاین، [[ ویژگیهای زیر را علاوه بر [ ارائه میکند:
تنها برتری test قابلیت حمل آن است.
ادامه دارد...