نقل‌قول ها - آموزش اسکریپت نویسی
X
تبلیغات
رایتل

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

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

#!/bin/bash

نقل‌قول ها

نقل‌قول‌ها

در بسیاری از زبانها، نقل‌قول‌ها اساساً برای مشخص نمودن آنکه متن محصور بین آنها به عنوان یک نوع دادهِ رشته‌ای تفسیر گردد، به کار می‌روند، اما در برنامه‌نویسی پوسته، تقریباً همه چیز یک رشته است، بنابراین نقل‌قول در پوسته اثرات و مقاصد بسیار متفاوتی دارد. چند نوع نقل‌قول وجود دارد که اصولاً روشهای متفاوتی از تفسیر محتویاتشان را فعال می‌کنند. متأسفانه، غالباً یادگیری قواعد آن برای نوآموزان دشوار است و در اِزای چند حالت ویژه و استثناهایی برای به خاطر سپردن، رفتارشان با متن تغییر می‌کند. همچنین متأسفانه، نقل‌قول در برنامه‌نویسی پوسته بینهایت اهمیت دارد. از مواردی است که شخص نمی‌تواند از یادگیری آن اجتناب کند. نقل‌قول نادرست در پوسته یکی از رایج‌ترین منابع باگهای اسکریپت‌نویسی و مسائل امنیتی می‌باشد. خوشبختانه، اکثر اوقات انجام درست آن با پیروی از چند راهبرد امکان پذیر است، اما در مورد نقل‌قول حدسی عمل نکنید. وقتی مردد هستید، تست کنید، و صفحه man در مورد چگونه تفسیر شدن نقل‌قولها در یک زمینه مفروض را بخوانید.

انواع نقل‌قول

  • نقل‌قولهای منفرد: (آپاستروف‌ها) از هرگونه تفسیر ویژه کاراکترهای میان آنها ممانعت می‌کنند. هر چیزی درمیان نقل‌قولهای منفرد لفظی است و به یک کلمه منفرد بسط می‌یابد. تنها موردی که نمی‌تواندنقل‌قولی منفرد بشود، خود کاراکتر نقل‌قول منفرد است.

  • نقل‌قولهای دوگانه: مهمترین و پیچیده‌ترین نوعِ نقل‌قول در برنامه‌نویسی پوسته می‌باشند. نقل‌قولهای دوگانه اجازه می‌دهند پوسته محتوای آنها را برای انواعی از بسط‌ها که با یک علامت $ پیشوند می‌شوند - بسط پارامترها، بسط‌های حسابی و جایگزینی‌های فرمان - تجزیه کند، در حالیکه با هر محتوای دیگر (غیر از backtickهای موروثی ‎(`)‎ تشریح شده در پایین و بسط تاریخچه ‎(!)‎) به طور لفظی رفتار می‌کنند. مهمتر از همه، در داخل نقل‌قولهای دوگانه تفکیک کلمه و بسط نام فایل بر چیزی اِعمال نمی‌گردند، همچنین آنها محتوایشان را از بسط ابرو، بسط مَد، جایگزینی پردازش، وتفسیر شدن به عنوان ترکیب دستوری تغییر مسیر نیز محافظت می‌کنند. نقل‌قولهای دوگانه نیز مانند نقل‌قولهای منفرد گنجاندن فوق‌کاراکترها و عملگرهای کنترل را بدون پوشش دادن توسط کاراکتر \، اجازه می‌دهند. نقل‌قولهای دوگانه همچنین روی بسط‌های پارامتر، جاییکه می‌توانند موقع بسط متغیرهای مختلط (آرایه‌ها و پارامترهای مکانی) تعداد کلمات را تحت تأثیر خود قرار بدهند، و بواسطه عدم اِعمال تفکیک کلمه و بسط نام‌فایل روی نتایج، دارای اثرات مهمی می‌باشند.

  • $'...'‎ و ‎$"..."‎: پوسته Bash دو شکل اضافی نقل‌قول را ارائه می‌کند -- نقل‌قولهای منفرد و دوگانهِ مقدم شده به وسیله یک علامت $ . البته، ‎$'...'‎ رایج‌تر است و درست مانند نقل‌قول منفرد عمل می‌کند به استثنای آنکه ترکیبات پوشش یافته توسط \ به طوریکه توسط استاندارد ‎ANSI C‎ مشخص شده، بسط داده می‌شوند. این امر یک طریقه راحت برای تعبیه کاراکترهای غیرقابل چاپ در میان رشته‌ها یا عبور دادن آنها به عنوان شناسه‌ها را میسر می‌سازد. شکل دوم ‎$"..."‎ است و برای پشتیبانی محلی‌سازی به کار می‌رود. هیچ یک از این موارد توسط POSIX تعریف یا ذکر نگردیده است، اما حداقل نوع ‎$'...'‎ به طور وسیع توسط Bash و Ksh93 و منسوبین پشتیبانی می‌شود.

  • گریز: کاراکتر گریز در Bash و ‎POSIX sh‎ کاراکتر \ است. علاوه بر برخی موارد استفاده معمول برای رشته‌های escape در سایر زبانها، یک کاراکتر گریز پوشش‌نیافته در یک مضمون عادی ارزیابی شناسه در Bash اساساً همان عمل نقل‌قول منفرد را انجام می‌دهد. یک \ دنبال شده با یک پارامتر glob، فوق‌کاراکتر، عملگر تغییر مسیر، و برخی کاراکترهای دیگر دارای معنی خاص، موجب می‌گردد آنها لفظی بشوند. کاراکترهای گریز در سایر مضمون‌ها، همچون متن‌های انطباق الگو و شناسه‌های متناظر با قالب ‎%b‎ در printf، شامل چند تابع مستندسازی نشده، مانند تغییر ترتیب مراجعهِ دستورات داخلی خاص در وضعیت non-POSIX (به بیان دیگر، بیش از آن که بنواند در یک مرور کوتاه گنجانده شود) دارای چند عملکرد دیگر می‌باشند. رایج‌ترین حالت به کار رفته کاراکتر گریز به عنوان یک شکلِ نقل‌قول، یک میانبرِ جایگزینِ نقل‌قول یگانهِ یک کاراکتر منفرد می‌باشد. به عنوان مثال شما می‌توانید به جای ‎'*'‎ بنویسید ‎ \*‎، یا چندین کلمه را با استفاده از ‎foo\ bar‎ به جای ‎'foo bar'‎ (یا به طور دقیق‌تر، ‎foo' 'bar‎) در یک کلمه منفرد ترکیب نمایید. زحمت: بیشتر در باره گریز بنویسید.

توجه: اگر چه backtickها ‎(`)‎ از نظر زبان‌شناسی نوعی نقل‌قول هستند، آنها در bash عملاً چیزی را نقل‌قول نمی‌کنند. در جایی که نقل‌قول در bash برای لفظی کردن(جزیی) داده‌ها به کار می‌رود، backtickها عملی کاملاً متفاوت انجام می‌دهند. آنها ترکیب دستوری قدیمی بورن برای جایگزینی فرمان هستند. آنها اساساً همان کار ‎$(...)‎ را انجام می‌دهند، اما یک مشت استثناهای شگرف نیز وجود دارد. به هر حال، آنقدر مهم نیستند: به خاطر وجود ‎$(...)‎ استفاده از آنها تقبیح می‌شود، و شما به راستی این روزها نباید این چیزها را در کد مدرن یا ابقا شده bash به کار ببرید. با وجود این اگر آنها را ببینید، نیاز به نقل‌قول را باطل نمی‌کنند(درست مانند ‎"$(command)"‎، باید آنها را نقل‌قول دوگانه کنید: ‎"`command`"‎)، و احتمالاً فقط باید آنها را با ‎$()‎ تعویض نمایید.

اثرات نقل‌قول

محافظت از فوق‌کاراکترهای پوشش نیافته

یک فرمان پوسته با استفاده از فضاهای سفید (صرف نظر از متغیر IFS ) و سایر فوق‌کاراکترهای پوسته، بوسیله شل به کلمات تجزیه می‌گردد. اولین عملکرد نقل‌قول، اجازه دادن به کلمات برای در بر داشتن این فوق‌کاراکترها می‌باشد.

echo '&'

بدون نقل‌قول‌ها، فوق‌کاراکتر & فرمان echo را در پس‌زمینه قرار خواهد داد. با نقل‌قول‌ها، فوق‌کاراکتر & واقعاً یک کلمه راتشکیل می‌دهد، و به عنوان شناسه به فرمان echo عبور داده می‌شود.

نقل‌قول‌ها عملاً به فرمان عبور داده نمی‌شوند.آنها توسط پوسته حذف می‌گردند (این فرایند هوشمندانه «پاکسازی نقل‌قول» نامیده می‌شود). در مثال فوق، فرمان echo فقط & را می‌بیند، نه نقل‌قولها را.

ممانعت از تفکیک فیلد و چشم‌پوشی از کاراکترهای الگوی glob

دومین هدف نقل‌قول ممانعت از تفکیک کلمه و globbing است. نتیجه یک جایگزینی نقل‌قول شده منفرد یا دوگانه، تحت تأثیر پردازش بیشتری قرار نمی‌گیرد. (نتیجه یک جایگزینی نقل‌قولی نشده قرار می‌گیرد.)

cp -- "$filename" "$destination"

در این مثال، نقل‌قول‌های دوگانه، کمیت هر پارامتر (متغیر) را از تحت تأثیر تفکیک کلمه قرار گرفتن یا انجام globbing روی فضای سفید و کاراکترهای عامِ (* یا ‎?‎ یا ‎[...]‎) محتوان آنها محافظت می‌کنند. بدون نقل‌قول‌ها، یک filename مانند ‎hot stuff.mp3‎ به دو کلمه تجزیه می‌گردید، و هر کلمه به عنوان یک شناسه جداگانه به فرمان cp عبور داده می‌شد. یا، یک filename شامل * همراه با فاصله در اطراف آن، به ازای هر فایل داخل دایرکتوری جاری یک کلمه تولید می‌کرد. که آنچه ما می‌خواهیم، نیست.

در اثر نقل‌قول‌ها، با هر کاراکترِ داخل کمیتِ پارامتر filename به طور لفظی رفتار می‌گردد، و کل کمیت، شناسه دوم فرمان cp می‌شود.

وقتی تردید دارید، همیشه بسط پارامترهایتان را نقل‌قول دوگانه کنید.

اگر احتیاج داشته باشید، می‌توانید انواع مختلف نقل‌قول‌ها را با هم به کار ببرید. برای مثال، اگر رشته‌ای داشته باشید که یک قسمت از آن دارای کاراکترهای ویژه زیادی می‌باشد که می‌خواهید نقل‌قول منفرد کنید و یک بسط پارامتر درون یک قسمت دیگر رشته است که باید نقل‌قول دوگانه شود، می‌توانید آنها رامخلوط کنید:

echo '!%$*&'"$foo"

هر تعداد از زیر رشته‌های نقل‌قولی شده از هر نوع، در این حالت می‌توانند به یکدیگر الحاق گردند. نتیجه (پس از بسط‌های مناسب در بخشهای نقل‌قول دوگانه شده) یک کلمه منفرد است.

بسط لیست‌های شناسه

نقل‌قول دوگانهِ ‎$@‎ یا ‎${array[@]}‎ دارای معنای ویژه‌ای می‌باشد. ‎"$@"‎ به لیستی از کلمات، که مقدار هر پارامتر مکانی یک کلمهِ لیست می‌شود، بسط می‌یابد. به همچنین ‎"${array[@]}"‎ به لیستی از کلمات به ازای هر عضو آرایه بسط می‌یابد. موقع کار کردن با پارامترهای مکانی یا محتوای یک آرایه به عنوان لیستی از کلمات، همیشه ترکیب نقل‌قول دوگانه را به کار ببرید.

نقل‌قول دوگانهِ ‎$*‎ یا ‎${array[*]}‎ به یک کلمه نتیجه می‌شود که الحاق تمام پارامترهای مکانی (یا عناصر آرایه) با اولین کاراکتر متغیر IFS در میان آنها می‌باشد. این مورد مشابه تابع join در سایر زبانهاست، اگر چه واقعیتِ آنکه فقط یک کاراکتر اتصال دارید گاهی اوقات محدودیت فلج‌کننده‌ای است.

مثالها

این هم چند مثال گوناگون برای نشان دادن آنکه کارها چگونه باید انجام گردد. برخی از این مثالها ترکیب دستوری bash/ksh را به کار می‌برند که در پوسته های POSIX محض کار نخواهند کرد.

تکرار صحیح روی پارامترهای مکانی با کاربرد ‎"$@"‎ نقل‌قولی شده. هرگز از یک ‎$@‎ یا ‎$*‎ نقل‌قولی نشده استفاده نکنید.

for file in "$@"; do
...
done

همچون مورد فوق، اما با یک آرایه.

for element in "${array[@]}"; do
...

تکرار صحیح روی شاخص‌ها

# و بالاتر ‎3.0‎ نگارش bash‎
for index in "${!array[@]}"; do
...

تمام بسط‌های متداول، بر متن داخل پرانتزهای یک تخصیص مرکب آرایه اِعمال می‌گردند، از جمله تفکیک کلمه و بسط نام مسیر، و باید به همان روش که اگر به عنوان شناسه‌ها به یک فرمان عبور داده می‌شدند، نقل‌قولی و با کاراکتر گریز پوشانده شوند.

# bash or ksh93
find_opts=('(' -iname '*.jpg' -o -iname '*.gif' -o -iname '*.png' ')')
find . "${find_opts[@]}" -print

اولی، یک رشته نقل‌قول منفرد شده، که با یک علامت نقل‌قول منفردِ نقل‌قول نشدهِ پوشش‌یافته با کاراکتر گریز دنبال می‌شود و پس از آن یک رشته نقل‌قولی منفرد. دومی، یک معادل غیر POSIX آن با کاربرد ‎$'...'

echo 'Don'\''t walk!'
echo $'Don\'t talk!'

جایگزینی‌های فرمان به سبک ‎‌$(...)‎ از این حیث که نقل‌قول محتوایشان کاملاً مستقل از احاطه کننده‌های آنها هستند، منحصر به فرد می‌باشند. این به معنای آنست که شما نباید نگران مسائل معاف کردن(escaping) نقل‌قول تو در تو باشید.

echo "The matching line is: $(grep foo "$filename")"

# .تودرتو هستند ‎$()‎ توجه کنید که نقل‌قول‌های داخل جایگزینی فرمان ‎
# .اشتباه است، اما در شل‌ها صحیح می‌باشد C این مورد از نظر یک برنامه‌نویس 

echo "The matching line is: $(grep foo "$filename")"
#                                      ^---------^    لایه داخلی نقل‌قولها‎
#                           ^^--------------------^   لایه میانی - جایگزینی فرمان‎
#    ^---------------------------------------------^  لایه خارجی نقل‌قولها‎

# گردد،  grep قبل از اینکه تحویل ‎$filename‎  بدون نقل‌قول‌های درونی مقدار‎
# می‌شد (globed) تفکیک کلمه و جانشین‎

# bash
ip=192.168.1.30
netmask=255.255.254.0
IFS=. read -ra ip_octets <<<"$ip"
IFS=. read -ra netmask_octets <<<"$netmask"
for i in 0 1 2 3; do
  ((ip_octets[i] &= netmask_octets[i]))
done
IFS=.; network="${ip_octets[*]}"; unset IFS

نقل‌قول سبکِ ‎$'...'‎ برای تفسیر backslash escapeها به کار می‌رود.

IFS=$' \t\n'
# ،را به یک رشته سه‌بایتی شامل یک فاصله  IFS متغیر‎
# .و یک سطر جدید تنظیم می‌کند tab یک ‎

# :موارد زیر همگی هم‌ارز هستند‎
echo $'hi\nthere\n'
printf '%s\n' hi there
# :سست شده‎
echo -e 'hi\nthere\n'
# ksh93 در پوسته
print 'hi\nthere\n'

موارد استثناء

الگوها

یک وضعیت مهم، جایی که نقل‌قول‌ها می‌توانند یک تأثیر ناخواسته داشته باشند، در متن‌های انطباق الگو می‌باشد. Bash نقل‌قول‌ها را برای موقوف کردن «ویژگی» الگوها و عبارت‌های منظم به کار می‌برد. با کاراکترهایی که در یک متن انطباق الگو به طور خاص تفسیر می‌شوند، موقعی که نقل‌قولی باشند خواه الگو از یک پارامتر بسط داده شود یا خیر، به طور لفظی رفتار می‌شود.

if [[ $path = foo* ]]; then
# عمل می‌کند glob نقل‌قولی نشده به عنوان یک ‎foo*‎  ‎

if [[ $path = "foo*" ]]; then
# نقل‌قولی شده یک رشته لفظی است ‎"foo*"‎ ‎

if [[ $path =~ $some_re ]]; then
# ‏(عبارت منظم توسعه‌یافته) عمل می‌کند ERE به عنوان یک ‎$some_re‎ محتویات ‎

if [[ $path =~ "$some_re" ]]; then
# به عنوان یک رشته لفظی رفتار می‌شود ‎$some_re‎ با محتویات ‎=~‎ با وجود عملگر‎

# Bash 4
# the "quoted" branch is taken.

g=a*[b]

case $g in
    "$g")
        echo 'quoted pattern'
        ;;&
    $g)
        echo 'unquoted pattern'
        ;;
esac

Here Documentها

پاکسازی نقل‌قول هرگز بر محتوای یک here document اِعمال نمی‌شود.

 $ arr=(words in array); cat <<EOF
> These are the "${arr[@]}"
> EOF
These are the "words in array"

نقل‌قول «رشته نگهبان» در heredoc باعث خواهد شد متن‌های heredoc برای بسط‌ها تجزیه شوند(مترجم: منظور این است که مثلاً ‎$HOME‎ همین طور دست نخورده باقی می‌ماند که بعداً بسط داده شود). این نوع heredoc نقل‌قول شده قدری خاص می‌باشد، به علت اینکه در تمام bash تنها موردی است که در آن یک رشته لفظی از یک متن انتخابی مشخص می‌شود که خودش موضوع هیچگونه تفسیر ویژه نیست، بلکه برای علامت زدن شروع سطرهای heredoc است.

{
    echo before
    eval "$(</dev/stdin)" # .مثل اینکه اینجا بوده اجرا می‌شود heredoc ‎
    echo after
} <<\EOF
# در اینجا قرار ندهید bash ابداً هیچ کُد‎
EOF

See also


CategoryShell

نقل‌قول‌ها (آخرین ویرایش ‎2013-01-05 09:40:48‎ توسط ormaaj)



پیوست

مترجم: به دلیل اهمیت مطلب و برای کامل‌تر نمودن آن، دومین پیوند از بخش See also صفحه فوق یعنی http://wiki.bash-hackers.org/syntax/quoting را نیز ترجمه و در ادامه این صفحه ضمیمه نموده‌ام.
escape و escaping برای لغو نمودن معنای ویژه کاراکترهای خاص و لفظی کردن آنها با استفاده از کاراکتر گریز (\) به کار می‌رود، من در این ترجمه به جای آن «گریز» یا «معاف کردن» و «معاف» را به کار برده‌ام.

نقل‌قولها و گریز

در حقیقت نقل‌قول و گریز روش مهمی برای تحت تأثیر قرار دادن رفتار Bash با ورودی شماست. سه نوعِ به رسمیت شناخته شده از آن وجود دارد:

  • معاف کردن یک کاراکتر با استفاده از یک \ (ممیز برعکس): ‎\$stuff
  • نقل‌قول ضعیف با نقل‌قول‌های دوگانه: ‎"stuff"
  • نقل‌قول قوی با نقل‌قول منفرد: ‎'stuff'

هر سه شکل دقیقاً دارای مفهوم یکسان هستند: آنها کنترل متداول روی تجزیه، بسط و نتایج بسط را به شما ارائه می‌کنند.

در کنار این گونه‌های اصلی، برخی روشهای نقل‌قول خاص‌تری (مانند تفسیر ‎ANSI-C escape‎ها در یک رشته) را در پایین ملاحظه خواهید نمود.

توجه این کاراکترهای نقل‌قول ("، نقل‌قول دوگانه و '، نقل‌قول منفرد) یک جزء گرامری هستند که تجزیه را تحت تأثیر قرار می‌دهند. به کاراکترهای نقل‌قول احتمالی که به عنوان متن به سطر فرمان عبور داده می‌شوند، مربوط نمی‌گردند! ترکیب نقل‌قول‌ها قبل از آنکه فرمان احضار شود حذف می‌شوند! نگاه کنید:

MYARG="\"my multiword argument\""
command $MYARG
### :نه نه نه: این سه رشته عبور می‌دهد‎
###      (1)  "my
###      (2)  multiword
###      (3)  argument"


### کُد فوق مانند این نیست ###
command "my multiword argument"

### به این نیاز دارید###
MYARG="my multiword argument"
command "$MYARG"

معاف کردن یک کاراکتر

معاف کردن یک کاراکتر در محل‌های مختلفی به کار می‌آید، همچنین در بسط‌ها و جایگزینی‌ها . به طور کلی،کاراکتری که برای Bash دارای معنی ویژه می‌باشد، مانند علامت دلار ‎($)‎ جهت معرفی انواع بسط، می‌تواند برای نداشتن آن معنی ویژه با کاربرد کاراکتر \ نقابدار بشود:

echo \$HOME is set to \"$HOME\"

  • \$HOME‎ بسط داده نخواهد شده چون دیگر ترکیب دستوری بسطِ متغیر نیست
  • کاراکترهای نقل‌قول برای لفظی شدن با \ نقاب زده می‌شوند - وگرنه توسط Bash تفسیر خواهند شد

رشته ‎\<newline>‎ (یک backslash غیر نقل‌قولی، دنبال شده با یک کاراکتر سطر‌جدید) به عنوان ادامه سطر تفسیر می‌گردد. از جریان ورودی حذف می‌شود و بنابراین به طور مؤثر صرفنظر خواهد شد. برای آرایش دادن به کُدتان آن را به کار ببرید:

# escapestr_sed()
# یک جریان را از ورودی استاندارد می‌خواند و کاراکترهای داخل متن را که می‌توانستند‎
# کاراکترهای خاص تفسیر گردند، معاف می‌کند sed توسط‎
escape_sed() {
 sed \
  -e 's/\//\\\//g' \
  -e 's/\&/\\\&/g'

}

کاراکتر backslash می‌تواند برای نقاب زدن به هر کاراکتری که دارای معنای خاص برای bash می‌باشد، به کار برود. استثناء: درون یک رشته نقل‌قولی منفرد (پایین را ببینید).

نقل‌قول ضعیف

داخل یک رشته نقل‌قولی ضعیف، تفسیر ویژه‌ای از این موارد وجود ندارد:

  • فاصله‌ها به عنوان جداکننده کلمات (در «تفکیک سطر فرمانِ اولیه» و در تفکیک کلمه!)
  • نقل‌قول‌های منفرد برای ارائه نقل‌قول قوی (پایین‌تر را ببینید)
  • کاراکترها برای انطباق الگو
  • بسط نام مسیر
  • جایگزینی پردازش

هر مورد دیگر، بخصوص بسط پارامتر، انجام می‌شود!

ls -l "*"
بسط داده نخواهد شد. ls کاراکتر لفظی * را به عنوان شناسه دریافت می‌کند. یک خطا بیرون خواهد داد مگر اینکه یک فایل با نام * داشته باشید.

echo "Your PATH is: $PATH"
همانطور که انتظار می‌رود عمل خواهد نمود. ‎$PATH‎ بسط داده می‌شود، زیرا تنها نقل‌قولی دوگانه(ضعیف) شده است.

اگر یک backslash در نقل‌قول دوگانه (نقل‌قول ضعیف) واقع شود، دو روش برای رفتار با آن وجود دارد

  • اگر baskslash با یک کاراکتر که حتی در داخل نقل‌قولهای دوگانه دارای معنای خاص است دنبال شود، backslash حذف می‌شود و کاراکتر متعاقب آن معنای ویژه‌اش را از دست می‌دهد
  • اگر backslash با کاراکتری بدون معنای ویژه دنبال شود، کاراکتر backslash حذف نمی‌گردد

بویژه این بدان معناست که ‎"\$"‎ تبدیل به $ خواهد شد، اما ‎"\x"‎ تبدیل به ‎\x‎ می‌شود.

نقل‌قول قوی

نقل‌قول قوی برای توضیح دادن بسیار ساده است

داخل یک رشته نقل‌قولی منفرد هیچ چیزی ‎(!!!!)‎ تفسیر نمی‌شود، به استثنای نقل‌قول منفرد که نقل‌قول را می‌بندد.

echo 'Your PATH is: $PATH'
آن ‎$PATH‎ بسط نخواهد یافت، به عنوان متن عادی معمولی تفسیر می‌گردد، زیرا به وسیله نقل‌قول‌های قوی احاطه گردیده است.

در عمل به معنای آن است که، برای ارائه یک متن مانند ‎Here's my test…‎ به عنوان یک رشته نقل‌قولی منفرد، شما برای بدست آوردن کاراکتر ‎"'"‎ به عنوان متن لفظی، باید از نقل‌قول منفرد خارج و دوباره وارد شوید:

# اشتباه‎
echo 'Here's my test...'

# صحیح‎
echo 'Here'\''s my test...'

# :پیشنهاد: ترکیب کردن نقل‌قول‌ها برای خوانایی نیز امکان‌پذیر است‎
echo "Here's my test"

رشته‌های ‎ANSI C‎ مانند

یک مکانیسم دیگر نقل‌قول هم وجود دارد که Bash عرضه می‌کند: رشته‌هایی که بواسطه رشته‌های گریز ‎ANSI C‎ مد نظر قرار می‌گیرند. ترکیب دستوری آن به این شکل است:

$'string'
که در آن رشته‌های گریز پایین در string کُد برداری می‌شوند:

کُد معنی
\" نقل‌قول دوگانه
\' نقل‌قول منفرد
\\ backslash
\a کاراکتر اعلام ترمینال(زنگ)
\b backspace
\e escape ‎(ASCII 033)‎
\E ‎escape (ASCII 033)‎ کد ‎\E‎ غیر استاندارد است
\f تغذیه کاغذ چاپگر
\n سطر جدید
\r سر سطر رفتن
\t tab افقی
\v tab عمودی
\cx یک کاراکتر ‎control-x،‎ برای مثال ‎$'\cZ'‎ برای چاپ رشته کنترلی ترکیب شده کنترل و Z یعنی ‎(^Z)‎
\uXXXX XXXX را به عنوان یک عدد هگزا دسیمال تفسیر کرده و کاراکتر معادل آن از مجموعه کاراکتر(۴ رقم) را چاپ می‌کند ‎(Bash 4.2-alpha)‎
\UXXXXXXXX XXXX را به عنوان یک عدد هگزادسیمال تفسیر نموده وکاراکتر معادل از مجموعه کاراکتر(۸ رقم) چاپ می‌کند ‎(Bash 4.2-alpha)‎
\nnn کاراکتر ۸ بیتی که مقدار آن عدد اکتال nnn می‌باشد (یکی برای سه رقم)
\xHH کاراکتر ۸ بیتی که مقدار آن عدد هگزادسیمال HH می‌باشد (یکی برای دو رقم هگز)

این مورد مخصوصاً موقعی مفید است که می‌خواهید کاراکترهای خاص را به عنوان شناسه به برخی برنامه‌ها ارائه کنید، مانند ارائه یک سطرجدید به sed.

با متنِ نتیجه چنان رفتار می‌شود که اگر نقل‌قولی منفرد شده بود. بسط‌ها دیگر صورت نمی‌گیرند.

ترکیب دستوری ‎$'...'‎ در ksh93 ایجاد شده، اما به اکثر پوسته‌های مدرن از جمله pdksh قابل حمل می‌باشد. یک مشخصات برای آن بواسطهSUS 7 صادره، پذیرفته شد. باز هم جدا افتاده‌هایی از قبیل اکثر گونه‌های ash شامل dash وجود دارند (غیر از busybox ساخته شده باویژگی‌های «سازگاری باbash»).

سراسری‌سازی(I18N)/محلی‌سازی(L10N)

یک علامت دلار دنبال شده با رشته نقل‌قولی دوگانه، برای مثال

echo $"generating database..."
به معنی محلی‌سازی است. اگر ترجمه معتبر برای آن رشته وجود داشته باشد، به جای متن داده شده به کار می‌رود. اگر نباشد، یا منطقه ‎C/POSIX‎ باشد، به سادگی علامت دلار صرفنظر می‌گردد که به یک رشته نقل‌قولی دوگانه عادی منجر می‌شود.

اگر رشته تعویض (ترجمه) شده باشد، نتیجه نقل‌قولی دوگانه است.

در صورتی که شما برنامه‌نویس C هستید: مقصود از ‎$"…"‎ مانند ‎gettext()‎ یا ‎_()‎ است.

برای مثالهای مناسب جهت محلی‌سازی اسکریپت‌هایتان، لطفاً پیوست I از راهنمای اسکریپت‌نویسی پیشرفته را ببینید.

توجه: یک حفره امنیتی وجود دارد. لطفاً مستندات gettext را بخوانید

اشتباهات متداول

لیست رشته‌ها در حلقه‌های for

حلقه کلاسیک for یک لیست از کلمات را برای تکرار روی آنها به کار می‌برد. البته این لیست در یک متغیر نیز می‌تواند باشد:

mylist="DOG CAT BIRD HORSE"

روش نادرست برای تکرار روی این لیست:

for animal in "$mylist"; do
    echo $animal
done

چرا؟ مطابق اصول تکنیکی، به علت نقل‌قول دوگانه، بسط ‎$mylist‎ به صورت یک کلمه دیده می‌شود. حلقه for دقیقاً یکبار با تنظیم animal معادلِ تمام لیست، تکرار می‌گردد.

روش درست برای تکرار در سرتاسر این لیست:

for animal in $mylist; do
    echo $animal
done

کار با فرمان test

فرمان test یا ‎[ … ]‎ ( فرمان کلاسیک test) یک فرمان عادی معمولی است، بنابراین قواعد گرامر فرمان عادی معمولی اِعمال می‌گردد. اجازه بدهید مقایسه رشته‌ای را به عنوان مثال بیاوریم:

[ WORD = WORD ]

شناسه ‎]‎ در انتها یک قرارداد است، اگر شما فرمان ‎which [‎ را تایپ کنید خواهید دید که در واقع یک فایل باینری با آن نام ‎([)‎ وجود دارد. بنابراین اگر این را به عنوان یک فرمان test می‌نوشتیم، اینطور می‌شد:

test WORD = WORD

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

mystring="my string"

و اکنون آن رشته را در برابر ‎"testword"‎ کنترل کنیم:

[ $mystring = testword ] # !!!اشتباه‎

این مقایسه ناموفق است! شناسه‌های بیش از اندازه‌ای برای مقایسه test وجود دارد. پس از انجام تمام بسط‌ها، در حقیقت این مورد را اجرا می‌کنید:

[ my string = testword ]
test my string = testword

که اشتباه است، زیرا my و string دو شناسه جداگانه می‌باشند.

بنابراین آنچه واقعاً نیاز دارید انجام بدهید، این است:

[ "$mystring" = testword ] # !!!درست‎

test 'my string' = testword

اکنون فرمان دارای سه پارامتر است، که بواسطه یک عملگر باینری (دو شناسه) معقول است.

نکته: داخل عبارت شرطی ‎([[ ]])‎ تفکیک کلمه توسط Bash انجام نمی‌شود، و از اینرو شما به نقل‌قول نمودن متغیرهای مرجع خود نیاز ندارید - آنها همواره به صورت «یک کلمه» دیده می‌شوند.

See also