it-swarm.asia

الفرق بين علامات الاقتباس المفردة والمزدوجة في Bash

في Bash ، ما هي الاختلافات بين علامات الاقتباس المفردة ('') والاقتباسات المزدوجة (""

430
jrdioko

لن تقتبس الاقتباسات الفردية أي شيء ، لكن الاقتباسات المزدوجة ستقوم بذلك على سبيل المثال: المتغيرات ، backticks ، بعض \ يهرب ، إلخ.

مثال:

$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")

دليل Bash لديه هذا القول:

3.1.2.2 اقتباسات مفردة

يحافظ تضمين الأحرف في علامات اقتباس مفردة (') على القيمة الحرفية لكل حرف داخل علامات الاقتباس. قد لا يحدث اقتباس واحد بين علامات الاقتباس المفردة ، حتى عندما يسبقه خط مائل عكسي.

3.1.2.3 اقتباسات مزدوجة

يحافظ تضمين الأحرف في علامات اقتباس مزدوجة (") على القيمة الحرفية لجميع الأحرف داخل علامات الاقتباس ، باستثناء $ و ` و \ وعند تمكين توسيع السجل !. تحتفظ الأحرف $ و ` بمعناها الخاص ضمن علامات اقتباس مزدوجة (انظر Shell Expansions ). يحتفظ الخط المائل العكسي بمعناه الخاص فقط عندما يتبعه أحد الأحرف التالية: $ أو ` أو " أو \ أو السطر الجديد. ضمن علامات اقتباس مزدوجة ، تتم إزالة خطوط مائلة عكسية متبوعة بأحد هذه الأحرف. خطوط مائلة عكسية الأحرف السابقة دون معنى خاص تترك دون تعديل. قد يتم اقتباس اقتباس مزدوج ضمن علامات اقتباس مزدوجة قبل تسبقه بخط مائل عكسي. في حالة التمكين ، سيتم تنفيذ توسيع السجل ما لم يتم تجاوز رمز ! الذي يظهر في علامات تنصيص مزدوجة باستخدام شرطة مائلة للخلف. لا يتم إزالة الخط المائل العكسي السابق !.

المعلمات الخاصة * و @ لها معنى خاص عندما تكون في علامات اقتباس مزدوجة (انظر Shell Parameter Expansion ).

443
Adam Batkin

إذا كنت تشير إلى ما يحدث عندما تردد شيئًا ما ، فإن علامات الاقتباس المفردة ستردد حرفيًا ما لديك ، في حين أن علامات الاقتباس المزدوجة ستقيِّم المتغيرات بينها وتُخرج قيمة المتغير.

على سبيل المثال ، هذا

#!/bin/sh
MYVAR=sometext
echo "double quotes gives you $MYVAR"
echo 'single quotes gives you $MYVAR'

سوف يعطي هذا:

double quotes gives you sometext
single quotes gives you $MYVAR
206
likso

الإجابة المقبولة رائعة. أقوم بوضع جدول يساعد في الفهم السريع للموضوع. يتضمن التفسير متغير بسيط a وكذلك صفيف مفهرس arr.

إذا وضعنا

a=Apple      # a simple variable
arr=(Apple)  # an indexed array with a single element

ثم echo التعبير في العمود الثاني ، سنحصل على النتيجة/السلوك الظاهر في العمود الثالث. يشرح العمود الرابع السلوك.

 # | Expression  | Result      | Comments
---+-------------+-------------+--------------------------------------------------------------------
 1 | "$a"        | Apple       | variables are expanded inside ""
 2 | '$a'        | $a          | variables are not expanded inside ''
 3 | "'$a'"      | 'Apple'     | '' has no special meaning inside ""
 4 | '"$a"'      | "$a"        | "" is treated literally inside ''
 5 | '\''        | **invalid** | can not escape a ' within ''; use "'" or $'\'' (ANSI-C quoting)
 6 | "red$arocks"| red         | $arocks does not expand $a; use ${a}rocks to preserve $a
 7 | "redapple$" | redapple$   | $ followed by no variable name evaluates to $
 8 | '\"'        | \"          | \ has no special meaning inside ''
 9 | "\'"        | \'          | \' is interpreted inside "" but has no significance for '
10 | "\""        | "           | \" is interpreted inside ""
11 | "*"         | *           | glob does not work inside "" or ''
12 | "\t\n"      | \t\n        | \t and \n have no special meaning inside "" or ''; use ANSI-C quoting
13 | "`echo hi`" | hi          | `` and $() are evaluated inside ""
14 | '`echo hi`' | `echo hi`   | `` and $() are not evaluated inside ''
15 | '${arr[0]}' | ${arr[0]}   | array access not possible inside ''
16 | "${arr[0]}" | Apple       | array access works inside ""
17 | $'$a\''     | $a'         | single quotes can be escaped inside ANSI-C quoting
18 | "$'\t'"     | $'\t'       | ANSI-C quoting is not interpreted inside ""
19 | '!cmd'      | !cmd        | history expansion character '!' is ignored inside ''
20 | "!cmd"      | cmd args    | expands to the most recent command matching "cmd"
21 | $'!cmd'     | !cmd        | history expansion character '!' is ignored inside ANSI-C quotes
---+-------------+-------------+--------------------------------------------------------------------

أنظر أيضا:

176
codeforester

وأوضح آخرون بشكل جيد للغاية ويريدون فقط إعطاء أمثلة بسيطة.

علامات الاقتباس المفردة يمكن استخدامها حول النص لمنع Shell من تفسير أي أحرف خاصة. يتم تجاهل جميع علامات الدولار والمسافات وعلامات النجمة والعلامات النجمية والشخصيات الخاصة الأخرى عند وضعها ضمن علامات اقتباس مفردة.

$ echo 'All sorts of things are ignored in single quotes, like $ & * ; |.' 

سوف يعطي هذا:

All sorts of things are ignored in single quotes, like $ & * ; |.

الشيء الوحيد الذي لا يمكن وضعه ضمن علامات اقتباس مفردة هو عرض أسعار واحد.

علامات الاقتباس المزدوجة التصرف بشكل مشابه للاقتباسات الفردية ، فيما عدا الاقتباسات المزدوجة لا تزال تسمح لشركة شل بتفسير علامات الدولار ، وعروض الأسعار السابقة وردود الخطوط المائلة العكسية. من المعروف بالفعل أن الخطوط المائلة للخلف تمنع تفسير حرف خاص واحد. يمكن أن يكون هذا مفيدًا ضمن علامات اقتباس مزدوجة إذا كانت علامة الدولار تحتاج إلى استخدام كنص بدلاً من متغير. كما يسمح بنقل علامات الاقتباس المزدوجة بحيث لا يتم تفسيرها على أنها نهاية السلسلة المقتبسة.

$ echo "Here's how we can use single ' and double \" quotes within double quotes"

سوف يعطي هذا:

Here's how we can use single ' and double " quotes within double quotes

قد يلاحظ أيضًا أن علامة اقتباس أحادية ، والتي يمكن تفسيرها على أنها بداية السلسلة المقتبسة ، يتم تجاهلها ضمن علامات اقتباس مزدوجة. ومع ذلك ، يتم تفسير المتغيرات واستبدالها بقيمها ضمن علامات اقتباس مزدوجة.

$ echo "The current Oracle SID is $Oracle_SID"

سوف يعطي هذا:

The current Oracle SID is test

علامات اقتباس للخلف تختلف تمامًا عن علامات الاقتباس المفردة أو المزدوجة. بدلاً من استخدامها لمنع تفسير الأحرف الخاصة ، تفرض علامات الاقتباس الخلفية فعليًا تنفيذ الأوامر التي تتضمنها. بعد تنفيذ الأوامر المغلقة ، يتم استبدال ناتجها بدلاً من علامات اقتباس الخلفية في السطر الأصلي. هذا سيكون أكثر وضوحا مع مثال.

$ today=`date '+%A, %B %d, %Y'`
$ echo $today 

سوف يعطي هذا:

Monday, September 28, 2015 
5
Sree

نظرًا لأن هذا هو الحل الفعلي عند التعامل مع علامات الاقتباس بـ bash ، سأضيف نقطة أخرى لم يرد عليها في الإجابات أعلاه ، عند التعامل مع عوامل الحساب في Shell.

يدعم bash Shell طريقتين للقيام بعملية حسابية ، واحدة محددة بواسطة أمر let المدمج و $((..)). السابق بتقييم تعبير حسابي في حين أن الأخير هو أكثر من عبارة مركبة.

من المهم أن نفهم أن التعبير الحسابي المستخدم مع let يخضع لتقسيم الكلمات وتوسيع اسم المسار تمامًا مثل أي أوامر أخرى لشركة Shell. نقلا عن السليم والهروب يحتاج إلى القيام به.

انظر هذا المثال عند استخدام let

let 'foo = 2 + 1'
echo $foo
3

يعد استخدام علامات الاقتباس المفردة هنا أمرًا جيدًا تمامًا هنا ، حيث لا توجد حاجة للتوسعات المتغيرة هنا ، فكر في حالة

bar=1
let 'foo = $bar + 1'

ستفشل فشلاً ذريعًا ، حيث إن/$bar ضمن علامات اقتباس مفردة سوف لا سوف تحتاج إلى أن تكون مقتبسة من

let 'foo = '"$bar"' + 1'

يجب أن يكون هذا أحد الأسباب ، يجب دائمًا اعتبار $((..)) عبر استخدام let. لأنه داخلها ، لا تخضع المحتويات لتقسيم الكلمات. المثال السابق باستخدام let يمكن كتابته ببساطة باسم

(( bar=1, foo = bar + 1 ))

تذكر دائمًا استخدام $((..)) بدون علامات اقتباس مفردة

على الرغم من أنه يمكن استخدام $((..)) مع علامات اقتباس مزدوجة ، فلا يوجد أي غرض نتيجة لذلك لا يمكن يحتوي على محتوى يحتاج إلى عرض أسعار مزدوج. فقط تأكد من أنها ليست واحدة ونقلت.

printf '%d\n' '$((1+1))'
-bash: printf: $((1+1)): invalid number
printf '%d\n' $((1+1))
2
printf '%d\n' "$((1+1))"
2

قد يكون في بعض الحالات الخاصة لاستخدام عامل $((..)) داخل سلسلة واحدة مقتبسة ، فأنت بحاجة إلى استيفاء علامات الاقتباس بطريقة يتم ترك المشغل بها بدون علامات اقتباس أو تحت علامات اقتباس مزدوجة. مثلا ضع في اعتبارك حالة ، عندما تكون مرتبطًا باستخدام عامل التشغيل داخل عبارة curl لتمرير عداد في كل مرة يتم فيها تقديم طلب ،

curl http://myurl.com --data-binary '{"requestCounter":'"$((reqcnt++))"'}'

لاحظ استخدام علامات الاقتباس المزدوجة المتداخلة في الداخل ، والتي بدونها يتم تمرير السلسلة الحرفية $((reqcnt++)) إلى حقل requestCounter.

1
Inian

يوجد تمييز واضح بين استخدام ' ' و " ".

عند استخدام ' ' حول أي شيء ، فلن يكون هناك "تحويل أو ترجمة". طبعت كما هي.

مع " " ، بغض النظر عما يحيط بها ، يتم "ترجمتها أو تحويلها" إلى قيمتها.

عن طريق الترجمة/التحويل أعني ما يلي: لن يتم "ترجمة" أي شيء ضمن علامات الاقتباس المفردة إلى قيمها. سيتم اتخاذها لأنها داخل اقتباسات. مثال: a=23 ، ثم echo '$a' سوف ينتج $a في الإخراج القياسي. في حين أن echo "$a" سوف ينتج 23 في الإخراج القياسي.

0
a_ran