2. نقلقولی کردن
تفکیک کلمه اهریمن درون BASH است که با جدیت تلاش میکند تازهواردها یا حتی کهنه سربازانی که سپر محافظ خود را زمین میگذارند، را غافلگیر کند.
اگر درک نکنید که تفکیک کلمه چطور کار میکند یا چه وقت اِعمال میشود، در استفاده از رشتهها و بسط پارامترها باید بسیار مراقب باشید. پیشنهاد میکنم اگر در مورد آگاهی خود تردید دارید،بیشتر در باره تفکیک کلمه مطالعه کنید.
بهترین روش محافظت خود از این جانور، نقلقولی کردن تمام رشتههایتان است. نقلقولها، رشتههای شما را به صورت یکپارچه نگاه میدارند تفکیک کلمه را از گسستن آنها منع میکنند. اجازه بدهید تشریح کنم:
$ echo Push that word away from me.Push that word away from me. $ echo\" Push that word away from me.\" Push that word away from me.
حال، تصور نکنید که تفکیک کلمه برای فرو ریختن فاصلههاست. آنچه به طور واقعی در این مثال اتفاق میافتد، آنست که در مثال اول، هر یک از کلمات جمله ما به عنوان یک شناسه( argument) جداگانه به echo تحویل داده میشود. BASH جمله ما را به کلمات تجزیه میکند، از فضای سفید برای تعیین آن که هر شناسه از کجا شروع و به کجا ختم میگردد، استفاده مینماید. در مثال دوم BASH وادار شده تمام رشته نقلقولی شده را با هم نگاه دارد. به این معنا که به شناسهها تفکیک نمیشوند و تمام رشته به عنوان یک شناسه به echo تحویل میشود. دستور echo همه شناسههایی که به آن داده شود را با یک فاصله مابین آنها در خروجی چاپ میکند. اکنون باید اساس تجزیه کلمه را متوجه شده باشید.
اینجاست که خطرناک میشود: تفکیک کلمه فقط در رشتههای لفظی اتفاق نمیافتد. این مطلب بعد از بسط پارامتر نیز رخ میدهد! در نتیحه، در یک شرایط رکود و خستگی، شاید برای انجام این خطا، به اندازه کافی کند ذهن شده باشید:
$sentence = \"Push that word away from me.\" $ echo$ sentence Push that word away from me. $ echo \"$ sentence \"Push that word away from me.
به طوری که ملاحظه میکنید، در دستور echo اول، سهلانگاری کرده و نقلقولها را از قلم انداخنهایم. اشتباه بود. BASH جمله ما را بسط داده و سپس از تفکیک کلمه برای تجزیه نتیجه بسط به شناسهها جهت تحویل به echo استفاده نموده. در دومین مثال، نقلقولها در اطراف بسط پارامتر جمله، اطمینان ایجاد میکند که BASH آن را به چندین شناسه پیرامون فضاهای سفید تجزیه نمیکند.
فقط فاصلهها نیستند که باید محافظت شوند. تفکیک کلمه در فاصلهها، tabها، سطر جدید، یا هر کاراکتر دیگری که در متغیر
$ echo \"$(ls \"-al )total 8 drwxr-xr-x 4 lhunath users 1 2007-06-28 13:13 \".\"/ drwxr-xr-x 102 lhunath users 9 2007-06-28 13:13 \"..\"/ -rw-r--r-- 1 lhunath users 0 2007-06-28 13:13 \"a\" -rw-r--r-- 1 lhunath users 0 2007-06-28 13:13 \"b\" -rw-r--r-- 1 lhunath users 0 2007-06-28 13:13 \"c\" drwxr-xr-x 2 lhunath users 1 2007-06-28 13:13 \"d\"/ drwxr-xr-x 2 lhunath users 1 2007-06-28 13:13 \"e\"/ $ echo$(ls -al )total 8 drwxr-xr-x 4 lhunath users 1 2007-06-28 13:13 \".\"/ drwxr-xr-x 102 lhunath users 9 2007-06-28 13:13 \"..\"/ -rw-r--r-- 1 lhunath users 0 2007-06-28 13:13 \"a\" -rw-r--r-- 1 lhunath users 0 2007-06-28 13:13 \"b\" -rw-r--r-- 1 lhunath users 0 2007-06-28 13:13 \"c\" drwxr-xr-x 2 lhunath users 1 2007-06-28 13:13 \"d\"/ drwxr-xr-x 2 lhunath users 1 2007-06-28 13:13 \"e\"/
در موقعیتهای بسیار نادری ممکن است، صرفنظر از نقلقولها مطلوب باشد. مواردی که شما نیاز به انجام تفکیک کلمه داشته باشید:
$friends = \"Marcus JJ Thomas Michelangelo\" $for friend in $ friends >do echo \"$ friend is my friend!\"; done Marcus is my friend! JJ is my friend! Thomas is my friend! Michelangelo is my friend!
اما، صادقانه؟ برای چنین حالاتی باید از آرایهها استفاده کنید. آرایهها این فایده را دارند که بدون نیاز به جداکننده صریح، رشتهها را جدا میکنند. این به آن معنا میباشد، که رشتههای شما میتوانند شامل هر کاراکتر معتبر(غیرتهی) باشند، بدون آنکه نگران جداکننده بودن کاراکتر باشید(مانند فاصله در مثال فوق). به کار بردن آرایه در مثال فوق ما را قادر میکند نام فامیل دوستان را نیز اضافه کنیم:
$friends =( \"Marcus The Rich\" \"JJ The Short\" \"Timid Thomas\" \"Michelangelo The Mobster\") $for friend in \"$ { friends [@] } \" >do echo \"$ friend is my friend!\"; done
توجه نمایید که در حلقه