Odpowiedzi:
Pojedyncze cudzysłowy niczego nie interpolują, ale podwójne cudzysłowy będą. Na przykład: zmienne, backticks, niektóre \
sekwencje specjalne itp.
Przykład:
$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")
Podręcznik Bash ma następującą treść:
Umieszczanie znaków w pojedynczych cudzysłowach (
'
) zachowuje dosłowną wartość każdego znaku w cudzysłowie. Pojedynczy cytat może nie wystąpić między pojedynczymi cudzysłowami, nawet jeśli poprzedzony jest odwrotnym ukośnikiem.Załączając znaków w cudzysłowach (
"
) chroni dosłowne wartości wszystkich znaków w cudzysłowie, z wyjątkiem$
,`
,\
i, gdy ekspansja historia jest włączona!
. Znaki$
i`
zachowują swoje specjalne znaczenie w podwójnych cudzysłowach (patrz Rozszerzenia powłoki ). Odwrotny ukośnik zachowuje specjalne znaczenie tylko wtedy, gdy następuje jedno z następujących znaków:$
,`
,"
,\
lub nowa linia. W ramach podwójnych cudzysłowów odwrotne ukośniki, po których następuje jeden z tych znaków, są usuwane. Ukośniki odwrotne poprzedzające znaki bez specjalnego znaczenia pozostają niezmodyfikowane. Podwójny cudzysłów można cytować w podwójnych cudzysłowach, poprzedzając go odwrotnym ukośnikiem. Jeśli ta opcja jest włączona, rozszerzanie historii będzie wykonywane, chyba że!
pojawienie się podwójnego cudzysłowu zostanie poprzedzone znakiem odwrotnego ukośnika. Ukośnik odwrotny poprzedzający!
nie jest usuwany.Parametry specjalne
*
i@
mają szczególne znaczenie, gdy w cudzysłowach (patrz Shell parametrów Expansion ).
git_prompt
tego gita, sugerują używanie go w ten sposób PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
, git zachęta , zgodnie z tym nie powinno działać. Czy jest coś specjalnego w PS#
zmiennych? lub dlaczego to działa, jeśli nie wykonuje interpolacji.
PS1
. Spróbuj echo $PS1
zobaczyć, co mam na myśli. Ale PS1
jest oceniany przed wyświetleniem (zobacz PROMPTING
sekcję na stronie podręcznika bash). Aby to przetestować, spróbuj PS1='$X'
. Nie otrzymasz monitu. Następnie uruchom X=foo
i nagle twój monit brzmi „foo” ( PS1
został oceniony po ustawieniu zamiast wyświetlenia , nadal nie pojawił się monit).
The Odpowiedź akceptowana jest wielki. Przygotowuję tabelę, która pomaga w szybkim zrozumieniu tematu. Wyjaśnienie dotyczy prostej zmiennej, a
a także tablicy indeksowanej arr
.
Jeśli ustawimy
a=apple # a simple variable
arr=(apple) # an indexed array with a single element
a następnie echo
wyrażenie w drugiej kolumnie, otrzymalibyśmy wynik / zachowanie pokazane w trzeciej kolumnie. Czwarta kolumna wyjaśnia zachowanie.
# | 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
---+-------------+-------------+--------------------------------------------------------------------
Zobacz też:
The special parameters * and @ have special meaning when in double quotes
więc skąd "*"
wynikają *
?
"$@"
i "$*"
są rozszerzeniami parametrów. "@"
i "*"
nie są.
echo "\'"
, zwraca mi \'
.
Jeśli odwołujesz się do tego, co się dzieje, gdy coś echo, pojedyncze cudzysłowy dosłownie odzwierciedlają to, co masz między nimi, podczas gdy podwójne cudzysłowy będą oceniać zmienne między nimi i generować wartość zmiennej.
Na przykład to
#!/bin/sh
MYVAR=sometext
echo "double quotes gives you $MYVAR"
echo 'single quotes gives you $MYVAR'
da to:
double quotes gives you sometext
single quotes gives you $MYVAR
Inni wyjaśnili bardzo dobrze i po prostu chcą podać proste przykłady.
Wokół tekstu można używać pojedynczych cudzysłowów, aby powłoka nie interpretowała żadnych znaków specjalnych. Znaki dolara, spacje, znaki handlowe, gwiazdki i inne znaki specjalne są ignorowane, jeśli są ujęte w pojedyncze cudzysłowy.
$ echo 'All sorts of things are ignored in single quotes, like $ & * ; |.'
Da to:
All sorts of things are ignored in single quotes, like $ & * ; |.
Jedyną rzeczą, której nie można umieścić w pojedynczych cytatach, jest pojedynczy cytat.
Podwójne cudzysłowy działają podobnie do pojedynczych cudzysłowów, z tym że podwójne cudzysłowy nadal pozwalają powłoce interpretować znaki dolara, cudzysłowy i odwrotne ukośniki. Wiadomo już, że ukośniki odwrotne uniemożliwiają interpretację jednego znaku specjalnego. Może to być przydatne w przypadku podwójnych cudzysłowów, jeśli znak dolara musi być użyty jako tekst zamiast zmiennej. Pozwala również na ucieczkę podwójnych cudzysłowów, więc nie są one interpretowane jako koniec łańcucha cytowanego.
$ echo "Here's how we can use single ' and double \" quotes within double quotes"
Da to:
Here's how we can use single ' and double " quotes within double quotes
Można również zauważyć, że apostrof, który inaczej byłby interpretowany jako początek cytowanego łańcucha, jest ignorowany w podwójnych cudzysłowach. Zmienne są jednak interpretowane i zastępowane ich wartościami w podwójnych cudzysłowach.
$ echo "The current Oracle SID is $ORACLE_SID"
Da to:
The current Oracle SID is test
Cudzysłowy są całkowicie odmienne od pojedynczych lub podwójnych. Zamiast zapobiegać interpretacji znaków specjalnych, cudzysłowy faktycznie wymuszają wykonanie zawartych w nich poleceń. Po wykonaniu załączonych poleceń ich dane wyjściowe są zastępowane w miejscu pierwotnych cudzysłowów. Zostanie to wyjaśnione na przykładzie.
$ today=`date '+%A, %B %d, %Y'`
$ echo $today
Da to:
Monday, September 28, 2015
Istnieje wyraźne rozróżnienie między użyciem ' '
i " "
.
Kiedy ' '
jest używany wokół czegokolwiek, nie wykonuje się „transformacji ani tłumaczenia”. Jest drukowane tak, jak jest.
Z " "
, cokolwiek to otacza, jest „tłumaczone lub przekształcone” do jej wartości.
Przez tłumaczenie / transformację rozumiem, co następuje: Cokolwiek w pojedynczych cudzysłowach nie zostanie „przetłumaczone” na ich wartości. Zostaną zrobione, ponieważ znajdują się w cudzysłowie. Przykład:, a=23
wtedy echo '$a'
produkuje $a
na standardowej mocy wyjściowej. Natomiast echo "$a"
będzie produkować 23
na standardowej mocy
Ponieważ jest to de facto odpowiedź na cytaty bash
, dodam jeszcze jeden punkt pominięty w powyższych odpowiedziach, gdy mamy do czynienia z operatorami arytmetycznymi w powłoce.
bash
Shell obsługuje dwa sposoby zrobić operacja arytmetyczna, zdefiniowany przez wbudowanylet
poleceniu i $((..))
operatora. Pierwszy ocenia wyrażenie arytmetyczne, podczas gdy drugi jest bardziej złożonym wyrażeniem.
Ważne jest, aby zrozumieć, że używane jest wyrażenie arytmetyczne let
dzieleniem słów, nazw ścieżek, podobnie jak inne polecenia powłoki. Dlatego należy wykonać prawidłowe cytowanie i ucieczkę.
Zobacz ten przykład podczas używania let
let 'foo = 2 + 1'
echo $foo
3
Używanie pojedynczych cudzysłowów tutaj jest absolutnie w porządku, ponieważ nie ma potrzeby tutaj zmiennych rozszerzeń, rozważ przypadek
bar=1
let 'foo = $bar + 1'
zawiodłoby nieszczęśliwie, ponieważ $bar
pojedyncze cytaty nie rozszerzyłyby się i należy je podwójnie podać jako
let 'foo = '"$bar"' + 1'
To powinien być jeden z powodów, dla $((..))
których zawsze należy rozważyć nad używaniem let
. Ponieważ w nim zawartość nie jest podzielona na słowa. Poprzedni przykład użycia let
można po prostu zapisać jako
(( bar=1, foo = bar + 1 ))
$((..))
bez pojedynczych cytatówChociaż $((..))
można go używać z podwójnymi cudzysłowami, nie ma to żadnego celu, ponieważ nie może zawierać treści, które wymagałyby podwójnego cudzysłowu. Tylko upewnij się, że nie jest to pojedynczy cytat.
printf '%d\n' '$((1+1))'
-bash: printf: $((1+1)): invalid number
printf '%d\n' $((1+1))
2
printf '%d\n' "$((1+1))"
2
Mogą występować w niektórych szczególnych przypadkach użycia $((..))
operatora w ciągu pojedynczego cudzysłowu, musisz interpolować cudzysłowy w taki sposób, aby operator nie pozostawił cudzysłowu lub był pod cudzysłowem. Np. Weź pod uwagę przypadek, gdy próbujesz użyć operatora wewnątrz curl
instrukcji, aby przekazać licznik za każdym razem, gdy żądanie jest wysyłane, wykonaj
curl http://myurl.com --data-binary '{"requestCounter":'"$((reqcnt++))"'}'
Zwróć uwagę na użycie zagnieżdżonych podwójnych cudzysłowów wewnątrz, bez których dosłowny ciąg znaków $((reqcnt++))
jest przekazywany do requestCounter
pola.
$((...))
również. Może to być „trochę” paranoiczne i IFS=0
na przykład mało prawdopodobne , ale na pewno nie jest niemożliwe :)
$[[...]]
składnia, ale może miałeś rację, zapominając o tym.