Відповіді:
Одиночні котирування нічого не інтерполюють, але подвійні лапки будуть. Наприклад: змінні, зворотні посилання, певні \
виходи тощо.
Приклад:
$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")
У посібнику Bash сказано:
Замикання символів в одиничних лапках (
'
) зберігає буквальне значення кожного символу в лапках. Одиночна цитата може не виникати між окремими цитатами, навіть коли передує зворотна косою рисою.Огороджувальні символи в подвійних лапках (
"
) зберігає буквальне значення всіх символів в лапках, за винятком$
,`
,\
та, коли розкриття історії включено,!
. Символи$
та`
зберігають своє особливе значення у подвійних лапках (див. Розширення оболонки ). Зворотний слеш зберігає свій особливий сенс тільки тоді , коли слід один з наступних символів:$
,`
,"
,\
або новий рядок У межах подвійних лапок знімаються нахили, які супроводжуються одним із цих символів. Підсумки, що передують символам без особливого значення, залишаються незмінними. Подвійна котировка може бути наведена в подвійних лапках, попередньо додавши її до зворотної косої риски. Якщо це ввімкнено, розширення історії буде виконуватися, якщо не з’явиться!
поява у подвійних лапки за допомогою зворотної косої риски. Нахил, який передує!
, не знімається.Спеціальні параметри
*
і@
мають особливе значення у подвійних лапках (див. Розширення параметра оболонки ).
git_prompt
цей git, вони передбачають, що вони пропонують його використовувати таким чином PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
, git prompt , відповідно до цього не повинно працювати. Чи є щось особливе у PS#
змінних? або чому це працює, якщо це не робить інтерполяція.
PS1
. Спробуйте echo $PS1
зрозуміти, що я маю на увазі. Але PS1
він оцінюється перед тим, як відображатись (див. PROMPTING
Розділ на баш-сторінці). Щоб перевірити це, спробуйте PS1='$X'
. У вас не буде запиту. Потім запустіть X=foo
і раптом ваш запит стає "foo" ( PS1
оцінювались, коли встановлено замість відображуваного, у вас все одно не буде запиту).
Загальноприйнятий відповідь великий. Я складаю таблицю, яка допомагає швидко розібратися в темі. Пояснення включає просту змінну 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
---+-------------+-------------+--------------------------------------------------------------------
Дивись також:
The special parameters * and @ have special meaning when in double quotes
те, як приходять "*"
результати *
?
"$@"
і "$*"
є розширенням параметрів. "@"
і "*"
не є.
echo "\'"
, повертає мене \'
.
Якщо ви маєте на увазі те, що відбувається, коли щось повторюєте, одиничні лапки будуть буквально перегукуватися на те, що у вас є між ними, тоді як подвійні лапки оцінюватимуть змінні між ними та виводять значення змінної.
Наприклад, це
#!/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
Інші пояснили дуже добре і просто хочуть навести прості приклади.
Окремі лапки можуть використовуватися навколо тексту, щоб запобігти інтерпретації оболонки будь-яких спеціальних символів. Знаки долара, пробіли, амперсанди, зірочки та інші спеціальні символи ігноруються, якщо вони укладені в межах однієї лапки.
$ 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
Існує чітка відмінність між використанням ' '
та " "
.
Коли ' '
навколо нічого не використовується, "трансформація чи переклад" не робиться. Він друкується як є.
З тим " "
, що б воно не оточувало, "перекладається чи перетворюється" на свою цінність.
Під перекладом / перетворенням я маю на увазі наступне: Все, що знаходиться в рамках однієї лапки, не буде "переведене" на їх значення. Вони будуть прийняті, як вони є всередині котирувань. Приклад:, a=23
тоді echo '$a'
буде вироблятися $a
на стандартному виході. Тоді як echo "$a"
буде вироблятися 23
на стандартній продукції.
Оскільки це фактична відповідь при роботі з цитатами bash
, я додам ще один момент, пропущений у відповідях вище, під час роботи з арифметичними операторами в оболонці.
bash
Оболонка підтримує два способи зробити арифметичну операцію, яка визначена з допомогою вбудованого в let
команді і $((..))
оператора. Перший оцінює арифметичний вираз, тоді як останній є більш складним твердженням.
Важливо розуміти, що арифметичний вираз, який використовується для, let
зазнає розбиття слів, розширення імені шляху, як і будь-які інші команди оболонки. Отже, належне цитування та втеча потрібно робити.
Дивіться цей приклад під час використання 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
поле.
$((...))
як добре. Це може бути "трохи" параноїком, і навряд чи це буде, IFS=0
наприклад, але це, безумовно, неможливо :)
$[[...]]
синтаксис, але, можливо, ви мали рацію, забувши його.