فصل 5. نقل‌قول

5.1- نقل‌قول متغیرها

به طور کلی هنگام ارجاع دادن به یک متغیر، محصور کردن نام آن متغیر در نقل‌قول‌های دوتایی عاقلانه است. این کار، تمام کاراکترهای داخل رشته نقل‌قول شده -- به استثنای کاراکترهای $‏، ` (نقل‌قول وارونه)، و ‎\ (escape)‎ -- را از تفسیر مجدد محافظت می‌کند. [1] نگهداری $ به عنوان یک کاراکتر خاص در نقل‌قول‌های دوگانه، ارجاع به متغیر نقل‌قولی شده (‎"$variable"‎‏)، یعنی تعویض متغیر با مقدار آن را ممکن می‌سازد ( مثال ‎4-1‎، را ملاحظه کنید).

برای پیشگیری از تفکیک کلمه، از نقل‌قول‌های دوگانه استفاده کنید.[2] یک شناسه محصور شده در نقل‌قول‌های دوگانه حتی اگر شامل جداکننده‌های فضای سفید باشد خودش را همچون یک کلمه منفرد حفظ می‌کند.

List="one two three"

for a in $List     # .از محل فضای سفید متغیر را به قطعه‌ها می‌شکند‎
do
  echo "$a"
done
# one
# two
# three

echo "---"

for a in "$List"   # .فضای سفید در یک متغیر منفرد حفظ می‌گردد‎
do #     ^     ^
  echo "$a"
done
# one two three

یک مثال دارای جزییات بیشتر:

variable1="a variable containing five words"
COMMAND This is $variable1    # :شناسه اجرا می‌کند ‎7‎ را با ‎COMMAND‎ 
# "This" "is" "a" "variable" "containing" "five" "words"

COMMAND "This is $variable1"  # :شناسه اجرا می‌کند ‎1‎ را با ‎COMMAND‎ 
# "This is a variable containing five words"


variable2=""    # تهی‎

COMMAND $variable2 $variable2 $variable2
                # .را بدون شناسه اجرا می‌کند ‎COMMAND‎  
COMMAND "$variable2" "$variable2" "$variable2"
                # .شناسه تهی اجرا می‌کند ‎3‎ را با ‎COMMAND‎  
COMMAND "$variable2 $variable2 $variable2"
                # .شناسه (دو فاصله) اجرا می‌کند ‎1‎ را با ‎COMMAND‎  

#  Stéphane Chazelas با تشکر از‎

Tip

در یک دستور echo محصور کردن شناسه در نقل‌قول‌های دوگانه تنها موقعی ضروری است که تفکیک کلمه یا محافظت از فضای سفید یک مسئله است.

مثال ‎5-1‎. نمایش متغیرهای عجیب و غریب

#!/bin/bash
# ‎weirdvars.sh:‎  نمایش متغیرهای غیرعادی

echo

var="'(]\\{}\$\""
echo $var        # '(]\{}$"
echo "$var"      # ‎'(]\{}$"‎    .تفاوتی ایجاد نمی‌کند

echo

IFS='\'
echo $var        # ‎'(] {}$"‎     به فاصله تبدیل شده است. جرا؟ ‎\‎ 
echo "$var"      # '(]\{}$"

# ارایه گردیده است ‎Stephane Chazelas‎ مثال فوق توسط‎

echo

var2="\\\\\""
echo $var2       #   "
echo "$var2"     # \\"
echo
# غیر مجاز است. چرا؟  ‎var2="\\\\""‎  اما
var3='\\\\'
echo "$var3"     # \\\\
# .اگرچه، نقل‌قول قدرتمند کار می‌کند‎


# ************************************************************ #
# .به طوریکه مثال نخست بالا نشان می‌دهد، نقل‌قول‌های تودرتو مجاز است

echo "$(echo '"')"           # "
#    ^           ^


# .گاه گاهی این مورد، مفید واقع می‌شود‎

var1="Two bits"
echo "\$var1 = "$var1""      # $var1 = Two bits
#    ^                ^

#  ...اشاره می‌کند ‎Chris Hiestand‎ یا همانطور که‎

if [[ "$(du "$My_File1")" -gt "$(du "$My_File2")" ]]
#     ^     ^         ^ ^     ^     ^         ^ ^
then
  ...
fi
# ************************************************************ #

نقل‌قول منفرد ‎(' ')‎ مشابه نقل‌قول‌های دوگانه عمل می‌کند، اما ارجاع به متغیر را اجازه نمی‌دهد، چون معنای ویژه $ خاموش می‌شود. داخل نقل‌قول‌های منفرد، هر کاراکتر خاص غیر از ' به طور لفظی تفسیر می‌شود. نقل‌قول‌های منفرد («نقل‌قول‌کردن کامل») را روش سختگیرانه‌تر نقل‌قول نسبت به نقل‌قول‌های دوگانه («نقل‌قول قسمتی») در نظر بگیرید.

چون حتی کاراکتر escape (\) داخل نقل‌قول‌های منفرد لفظی تفسیر می‌شود، تلاش برای محصور کردن یک نقل‌قول منفرد در داخل نقل‌قول‌های منفرد موجب نتیجه مورد انتظار نخواهد شد.
echo "Why can't I write 's between single quotes"

echo

# .روش پر پیچ و خم‎
echo 'Why can'\''t I write '"'"'s between single quotes'
#    |-------|  |----------|   |-----------------------|
# شده ‎escap‎ سه رشته نقل‌قول منفرد شده، با نقل‌قول‌های منفرد‎
#                            .و نقل‌قول شده در مابین آنها
#        .است ‎Stéphane Chazelas‎ این مثال اهدایی به وسیله‎

یادداشت‌ها

[1]

بسته‌بندی ! داخل نقل‌قول‌های دوگانه موقعی که در خط فرمان به کار برود، یک خطا به معرض نمایش می‌گذارد. این همچون یک فرمان تاریخچه تفسیر می‌شود. اگر چه، داخل یک اسکریپت، چنین مشکلی رخ نمی‌دهد چون ساز و کار تاریخچه Bash در آن هنگام غیر فعال می‌گردد.

مورد نگران کننده‌تر رفتار ظاهراً متناقض \ در داخل نقل‌قول‌های دوگانه و بویژه به دنبال یک فرمان ‎echo -e‎ است.

bash$ echo hello\!
hello!
bash$ echo "hello\!"
hello\!


bash$ echo \
>
bash$ echo "\"
>
bash$ echo \a
a
bash$ echo "\a"
\a

bash$ echo x\ty
xty
bash$ echo "x\ty"
x\ty

bash$ echo -e x\ty
xty
bash$ echo -e "x\ty"
x       y

نقل‌قول‌های دوگانه متعاقب یک echo گاهی اوقات \ را معاف(escape) می‌کنند. علاوه براین، گزینه ‎-e‎ برای echo باعث می‌شود ‎"\t"‎ به عنوان یک tab تفسیر بشود.

(با تشکر از ‎Wayne Pollock‎، برای اشاره کردن به این مورد، و از Geoff Lee و Daniel Barclay برای تشریح آن.)

[2]

«تفکیک کلمه» در این زمینه، به معنی تقسیم کردن یک رشته کاراکتری به شناسه‌های مستقل و جدا از یکدیگر است.