این صفحه کوششی است برای لیست کردن برخی از رایجترین bashismها، یعنی ویژگیهایی که توسط POSIX تعریف نشدهاند (در dash، یا /bin/sh متداول، کار نخواهند کرد). احتمالاً شامل تمام جزئیات نخواهد بود. همچنین توجه نمایید که ما در باره "bashism" صحبت میکنیم، زیرا این ویکی به طور عمده متمرکز بر bash میباشد، اما چون اکثر ویژگیهای اسکریپتنویسی Bash از ksh مشتق گردیده است تعدادی(تقریباً همه) از این ملحقات احتمالاً با تفاوتهایی در جزئیات، حداقل در برخی پوستههای دیگر مانند ksh یا zsh نیز کار میکنند. POSIX تعداد بسیار کمتری از آنها را لازم دانسته است.
در bash کار میکند |
تغییر برای dash |
توضیحات |
|
تعریف توابع |
function f { echo hello world; } |
f() { echo hello world; } |
"function" توسط POSIX تعریف نگردیده است، فقط شکل "name ()" وجود دارد. ترکیب function f {...} در ksh آغاز گردید (پیشتر از ترکیب دستوری Bourne). در ksh هر دو کل وجود دارد، اما در پیادهسازیهای AT&T توابع تعریف شده با "function" به طور مختصری متفاوت کار میکنند. zsh نیز بدون تمایز هر دو ترکیب را پشتیبانی میکند. |
در case |
;;& ;& etc |
هیچ. case را دوگانه کنید( برای اجتناب از دوبار تکرار کد، از تابع استفاده کنید) |
;;& و ;& در bash4 هست و در POSIX تعریف نشده. ksh پیادهسازی AT&T (از ksh88e، جایی که آغاز گردید)، MirBSD ksh (از R40) و zsh (از 3.1.2) دارای ;& هستند، اما ;;& را ندارند |
حلقه forعددی سَبک C |
for ((i=0; i<3; i++)); do |
i=0 ; while [ "$i" -lt 3 ]; do |
این ترکیب توسط POSIX تعریف نشده. در ksh93 جایی که سرچشمه آن است و در zsh وجود دارد. |
بسط رشتهها |
echo $'hello\tworld' |
printf "hello\tworld\n" |
به طور تاریخی $' ' تا سال 2008 توسط POSIX تعریف نشده بود، اما در نگارش بعدی پذیرفته شده است. http://austingroupbugs.net/view.php?id=249. در ksh93 آغاز شد و توسط zsh نیز پشتیبانی شد. |
glob توسعهیافته |
+( ) @( ) !( ) *( ) |
همیشه امکان پذیر نیست، گاهی میتوانید از چند globs استفاده کنید، گاهی اوقات میتوانید find(1) را به کار ببرید |
توسط POSIX تعریف نشده. در ksh آغاز گردید. به وسیله zsh با یک گزینه مانند bash پشتیبانی شده است. |
select |
select |
برخی نظرات: خودتان منو را پیادهسازی کنید، از برنامهای مانند dialog استفاده کنید |
در POSIX تعریف نشده. در ksh شروع شد، در zsh نیز حاضر است. |
بسط ابرو، به عنوان مثال {a,b,c} یا {1..10} در POSIX تعریف نشده است. هر دو شکل در ksh93، و شکل اول در ksh قدیمیتر و mksh وجود دارد. . اولی در csh آغاز گردید، دومی در zsh.
جایگزینی پردازش <( ) و >( ) توسط POSIX تعریف نشده، اما میتواند با FIFOها شبیهسازی شود: به جای foo <(bar)، بنویسید mkfifo fifo; bar > fifo & foo fifo (در اصل این طریقهایست که جایگزینی پردازش در سیستم عاملهایی که مکانیسمی مانند /dev/fd/ را ندارند، برای ارجاع به لولههای بدون نام با نام فایلها، پیادهسازی میشود). در ksh93 شروع گردید، در zsh نیز وجود دارد.
فهرست بسطهای تعریف نشده در POSIX:
${name:n:l} -- میتوانید از این $(expr "x$name" : "x.\{,$n\}\(.\{,$l\}\)") استفاده کنید. این بسط در ksh93 شروع شد و در zsh نیز موجود است.
${name/foo/bar} -- بعد از تغییر الگوهای پوسته به عبارتهای منظم میتوانید از این سطرِ فرمان $(printf '%s\n' "$name" | sed 's/foo/bar/') استفاده کنید. این ترکیب در ksh93 آغاز شد و در mksh، و zsh، موجود است، اما بسط جایگزینی ksh93 با قالب Bash تفاوت دارد.
${!name} -- مختص bash، برای رسیدن به نتایج مشابه استفاده از eval امکان پذیر است، اما مستلزم توجه بسیار به جزئیات خواهد بود، پرسش و پاسخ شماره ۶ را ببینید.
رفتار عملگرهای #، ##، %، و %% موقع استفاده همراه پارامترهای @ یا * در مستندات POSIX و ksh88 مشخص نگردیده است. Dash حذف حواشی برای نتیجه پاکیزه شده را فراهم میکند. mksh و pdksh با آن به عنوان یک بسط نامعتبر رفتار میکنند.
توجه کنید که استفاده از $( ) دارای اثرات جانبی حذف سطر جدید انتهایی از نتایج است.
آرایهها در POSIX تعریف نشدهاند( اما در ksh موجودند)، چارهجویی کلی آسانی برای آرایهها وجود ندارد. در اینجا اشاراتی شده است::
# یک فرمان را پویا میسازد( پرسش و پاسخ شماره ۵۰ را ببینید ) set -- 'mycommand' 'needs some complex' 'args' "$@" # i دستیابی پارامتر شماره set -- one two three i=2 eval "var=\${$i}" # .باید در تمام موارد توسط اسکریپت کنترل بشود. اگر از آثار جانبی همچون ورودی کاربر، تاثیر بپذیرد، معتبر سازی نیرومندی لازم میگردد i printf '%s\n' "$var"
استفاده از IFS و set -f
eval قدرتمند، اما آسان برای سوءاستفاده در روشهای پُرمخاطره است. فرمان Eval و مسائل امنیت را ببینید.
|
در bash کار میکند |
تغییر برای کار کردن در dash |
توضیحات |
test ساده |
[[ |
از [ و نقلقولهای دوگانه در اطراف بسطها استفاده کنید [ "$var" = "" ] |
[[ توسط POSIX تعریف نشده، در ksh شروع شوه و در zsh نیز وجود دارد |
انطباق الگو |
[[ foo = *glov ]] |
از case یا expr یا grep استفاده کنید |
پرسش و پاسخ شماره ۴۱ را ببینید |
بررسی برابری |
== |
به جای آن از = استفاده کنید |
در POSIX فقط = تعریف گردیده |
مقایسه لغوی به ترتیب دیکشنری. |
< > |
بدون تغییر |
در dash, ksh, yash و zsh موجود است، اما در POSIX تعریف نگردیده است. برای روشهای چارهجویی ممکن یادداشت پایین را ببینید. |
مقایسه زمانهای ویرایش |
[[ file1 -nt file2 ]] یا -ot |
[ "$(find 'file1' -prune -newer 'file2')" ] یا [ "file1" -nt "file2" ] |
گزینه -prune برای پرهیز از جستجوی بازگشتی لازم است، در dash، ksh، yash و zsh وجود دارد. -nt و -ot توسط POSIX تعریف نگردیدهاند. |
بررسی آنکه آیا دو فایل hardlink هستند |
[[ file1 -ef file2 ]] |
[ "file1" -ef "file2" ] |
-ef در POSIX تعریف نگردیده، اما در ksh، yash، zsh و Dash وجود دارد. |
(( )) |
(( )) (بدون $) مانند یک فرمان بر خودش عمل میکند |
برای مقایسه ساده: [ -lt ] (and -ne -gt -ge) یا [ "$((3 + 1 < 5))" -ne 0 ]. |
در ksh (جایی که از آن آغاز شده) و zsh وجود دارد |
یادداشت: برای مقایسههای لغوی چند برنامه استاندارد POSIX میتوانند به کار بروند. مثالهای زیر در صورتیکه محتوای $a قبل از $b مرتب گردد، یک وضعیت خروج صحیح (صفر) برگشت میدهند.
awk 'BEGIN { exit !(ARGV[1] "" < "" ARGV[2]) }' "$a" "$b"
expr "x$a" "<" "x$b" >/dev/null
اگر متغیرها شامل کاراکترهای سطر جدید نباشند: printf "%s\n" "x$a" "x$b" | sort -C ( در صورتیکه $a و $b برابر باشند نیز صحیح برگشت میدهد)
|
در bash کار میکند |
تغییر برای dash |
توضیحات |
پیش/پس افزایش/کاهش |
++ -- |
i=$((i+1)) یا : $((i+=1)) |
- |
عملگر کاما |
, |
: "$((...))"; cmd "$((...))" |
عملگر کاما به طور گسترده تقریباً توسط همه به استثنای dash و yash پشتیبانی شده است -- حتی توسط posh و Busybox. |
- |
let یا ((...)) |
[ "$((...))" -ne 0 ] |
به علت محدودیت کاما در بالا، let نمیتواند بدون یک حلقه به طور دقیق شبیهسازی گردد. |
|
در bash کار میکند |
تغییر برای dash |
توضیحات |
تغییر مسیر stdout و stderr با هم |
>& and &> |
command > file 2>&1 or command 2>&1 | othercommand |
- |
|
|& (bash4) |
command 2>&1 | othercommand |
با ksh ناسازگار است. حتی در Bash توصیه نمیشود. فقط 2>&1 را به کار ببرید. |
دونسخه کردن و بستن |
m>&n- m<&n- |
m>&n n>&- |
توسط POSIX تعریف نگردیده |
herestring |
<<<"string" |
echo | command، یا یک here document به منظور پرهیز از یک پوسته فرعی (<<EOF) |
- |
echo -n یا -e -- استاندارد POSIX هیچ گزینهای تعریف نکرده، و از این گذشته اجازه میدهد echo -e رفتار پیشفرض باشد. به جای آن printf "%s\n" (برای echo معمولی) یا printf "%b\n" (برای echo -e) را به کار ببرید، از \n به منظور شبیهسازِی echo -n دست بکشید.
printf -v توسط POSIX تعریف نمیشود، و فقط Bash آن را پشتیبانی میکند. قالبهای %q و %()T توسط POSIX تعریف نمیشوند، اما به وسیله ksh93 و Bash پشتیبانی میگردند. قالبهای a، A، e، E، f، F، g، و G در POSIX برای printf(1) عمل نمیکنند اما dash ظاهراً %f، %e، %E، %g، و %G را پشتیبانی میکند.
read -- تنها گزینه تعریف شده در POSIX گزینه -r است، ksh یک مجموعه از گزینههای مختلف دارد که فقط به طور جزئی با bash همپوشانی دارد.
shopt، و بنابراین تمام گزینههایی که فراهم میکند (extglob و nullglob و dotglob وغیره) توسط POSIX تعریف نشدهاند و مخصوص bash میباشند.
local -- معادلی در POSIX وجود ندارد. میتوانید از $funcname_varname برای کاهش احتمال تضاد، استفاده کنید، اما حتی آن نیز برای توابع بازگشتی کافی نیست . میتوانید تضمین کنید که فراخوانیهای بازگشتی در محیط پوستههای فرعی رخ میدهد (همینطور یک کپی "local" از تمام متغیرها وجود دارد)، یا تمام متغیرهای محلی را به عنوان پارامتر عبور بدهید( زیرا پارامترهای مکانی $@، و $1، و $2، و غیره به درستی local هستند ). dash به طور صریح از local به عنوان یک الحاقیه غیر Posix استفاده میکند، در عوض ksh از typeset استفاده مینماید، که مانند declare پوسته bash کار میکند. local به وسیله LSB و معیارهای سیاست Debian حکم گردیده، اگرچه فقط ترکیب دستوری local varname (نه local var=value) مشخص شده است. یک پیادهسازی از یک متغیر پشته برای پوستههای POSIX را در اینجا میتوان یافت.
|
در bash کار میکند |
تغییر برای dash |
توضیحات |
نگهداری یک رکورد از زمانها |
SECONDS |
before=$(date +%s) ....seconds=$(( $(date +%s) - $before)) |
date +%s موافق POSIX نیست،برای اطلاعات بیشتراین پرسش و پاسخ را ببینید. در ksh وجود دارد |
تولید یک عدد تصادفی |
RANDOM |
random=$(awk 'BEGIN{srand(); printf "%d\n",(rand()*256)}') یک عدد بین 0 و 256 میدهد. |
اطمینان حاصل نمایید که آموختهاید srand() و rand() چه کار میکنند، یعنی در صورتیکه چندین مرتبه به سرعت awk را فراخوانی کنید این روش شکست میخورد. در عوض تمام اعدادی را که لازم دارید، داخل awk تولید کنید. برخی سیستمهاهمچنین /dev/random and /dev/urandom را هم فراهم میکنند، اما این مورد ضرورتاً توسط استاندارد POSIX حکم نمیشود. ksh دارای RANDOM هست. |
به دست آوردن وضعیت تمام فرمانها در یک لوله |
PIPESTATUS |
راه حل ساده: |
مخصوص bash، این پرسش و پاسخ و این اسکریپت وضعیت لوله برای پوسته POSIX را ببینید |
به دست آوردن نام تمام(های) توابع یا تابع جاری |
FUNCNAME |
?? |
مختص bash، پرسش stackoverflow را ببینید |
مستندات bash دارای لیستی از تفاوتهای میان bash در حال اجرا در وضعیت POSIX و یک bash معمولی، است.
به خاطر داشته باشید که bash در وضعیت POSIX فقط متعهد به اجرای یک پوسته نوشتهشده مطابق معیارهای POSIX است. این به معنای آن نیست که اگر شما در اسکریپتهایتان از bashismها استفاده کنید، ناموفق خواهد شد.
ویکی Ubuntu نیز دارای صفحهای است که تفاوتها را شرح میدهد.
Bashism (آخرین ویرایش 2013-10-24 13:06:44 توسط GreyCat)