این تله است، و باید به ترتیب دقیقی که، تفکیک کنندهBash هر مرحله را انجام میدهد، توجه شود.
بسیاری اشخاص وقتی ابتدا ترکیب var=value command را کشف میکنند و پیمیبرند که چطور در طول اجرای فرمان به طور موقتی متغیر را تنظیم مینماید، نهایتاً یک مثال مشابه این یکی میسازند و سردرگم میشوند که چرا آنچه را انتظار دارند انجام نمیدهد.
به عنوان یک توضیح:
$ unset foo $ foo=bar echo "$foo" $ echo "$foo" $ foo=bar; echo "$foo" bar
علت اینکه دستور اول یک سطر خالی چاپ میکند به خاطر ترتیب این مراحل است:
بسط پارامتر $foo اول انجام میشود. یک رشته تهی برای عبارت نقلقولی شده جایگزین میشود.
بعد از آن، Bash محیط موقتی را برقرار میکند و foo=bar را در آن قرار میدهد.
فرمان echo با یک رشته تهی به عنوان شناسه، و foo=bar در محیطش اجرا میشود. اما چون فرمان echo به متغیرهای محیط توجه ندارد، آن را نادیده میگیرد.
این نگارش آنطور که ما انتظار داریم عمل میکند:
$ unset -v foo $ foo=bar bash -c 'echo "$foo"' bar
در این حالت، مراحل زیر انجام میشوند:
یک محیط موقت همراه با foo=bar داخل آن، تنظیم میشود.
bash از داخل آن محیط فراخوانی میشود، و -c و echo "$foo" به عنوان دو شناسهاش به آن تحویل میشوند.
Bash پردازش فرزند $foo را با مقدار آن در محیط بسط میدهد و آن مقدار را تحویل echo میدهد.
در تمام حالتها کاملاً واضح نیست که چرا اشخاص این سؤال را از ما میپرسند.اکثراً به نظر میرسد آنها به جای تلاش برای حل یک مشکل معین، درباره رفتار آن کنجکاو میباشند، بنابراین، من سعی نمیکنم مثالهایی در باره «روش صحیح انجام مواردی مانند این» تحویل بدهم، چون یک مشکل حقیقی برای حل کردن وجود ندارد.
موقعیتهای ویژهای در Bash وجود دارد که در آنها درک این مطلب میتواند مفید باشد. مثال زیر را ملاحظه کنید:
arr=('Var 1' 'Var 2' 'Var 3' 'Var 4') # ";" وصل کردن هر عنصر آرایه با # نمودن unset سپس و IFS تنظیم متغیر :روش سنتی IFS=\; joinedVariable="${arr[*]}" unset -v IFS # به طور موقت تنظیم شود. eval برای مدت اجرای IFS روش جایگزین، متغیر # 4.3.0 در نگارشهای کوچکتر از Bash راهکار نقلقول دوگانه یک باگ IFS=\; command eval 'JoinedVariable="${arr[*]}"'
در اینجا، پیشنهاد eval سادهتر و بیشتر برازنده است(در نظر شما! -- GreyCat). برای تضمین امنیت موقع به کارگیری eval باید دقت مناسب به عمل آید. پیشوند command برای تمام پوستههای غیر از Bash به اضافه Bash در حالت POSIX لازم است( http://wiki.bash-hackers.org/commands/builtin/eval#using_the_environment) را ببینید. این مورد در نگارشهای اخیر zsh به سبب یک پسرفت آشکار، (رفتار مستند شده جهش به سوی setopt POSIX_BUILTINS)، یا busybox به علت یک باگ که در این حالت تخصیصهای محیط برای پخش شدن ناموفق میگردند، کار نخواهد کرد. (هر کس به اندازه کافی علاقمند است با خیال راحت باگها را اصلاح کند).
پرسش و پاسخ 104 (آخرین ویرایش 2013-07-23 12:04:16 توسط GreyCat)