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 ).
Co powiesz na to, że gdy używasz git_prompttego 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.
ekiim
@ekiim Dokładny tekst jest ustawiony (niezmieniony) na PS1. Spróbuj echo $PS1zobaczyć, co mam na myśli. Ale PS1jest oceniany przed wyświetleniem (zobacz PROMPTINGsekcję na stronie podręcznika bash). Aby to przetestować, spróbuj PS1='$X'. Nie otrzymasz monitu. Następnie uruchom X=fooi nagle twój monit brzmi „foo” ( PS1został oceniony po ustawieniu zamiast wyświetlenia , nadal nie pojawił się monit).
Adam Batkin
262
The Odpowiedź akceptowana jest wielki. Przygotowuję tabelę, która pomaga w szybkim zrozumieniu tematu. Wyjaśnienie dotyczy prostej zmiennej, aa 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 echowyraż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
---+-------------+-------------+--------------------------------------------------------------------
Przyjęta odpowiedź brzmi w końcu, The special parameters * and @ have special meaning when in double quoteswięc skąd "*"wynikają *?
anddero
2
@ Karl-AnderoMere, ponieważ w ogóle nie są one rozwijane jako parametry. "$@"i "$*"są rozszerzeniami parametrów. "@"i "*"nie są.
Charles Duffy,
@CharlesDuffy Dzięki, to ma teraz sens!
anddero
3
Numer 9 echo "\'", zwraca mi \'.
MaxGyver
@MaxGyver: dzięki za wskazanie. Zaktualizowałem odpowiedź.
codeforester
233
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.
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=23wtedy echo '$a'produkuje $ana standardowej mocy wyjściowej. Natomiast echo "$a"będzie produkować 23na standardowej mocy
Co rozumiesz przez „tłumaczenie” lub „transformacja”?
Nico Haase,
Ta odpowiedź jest dość myląca i nie dodaje niczego do istniejących dobrych odpowiedzi.
codeforester
2
To była, moim zdaniem, krótka zwięzła odpowiedź, bez nadmiernego wysiłku, co było dla mnie łatwe do zrozumienia. Mówiąc tłumaczenie / transformacja, mają na myśli podwójne cudzysłowy rozwiną zmienną, a pojedyncze cudzysłowy nie rozwiną zmiennej.
B_e_n_n_y_
1
Tak, to najlepsza odpowiedź. To powinna być zaakceptowana odpowiedź.
Jamey Kirby
3
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.
bashShell 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ż $barpojedyncze 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 letmożna po prostu zapisać jako
(( bar=1, foo = bar +1))
Zawsze pamiętaj, aby używać $((..))bez pojedynczych cytatów
Chociaż $((..))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.
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 curlinstrukcji, aby przekazać licznik za każdym razem, gdy żądanie jest wysyłane, wykonaj
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 requestCounterpola.
Charles Duffy sprawia dobrą sprawę tutaj na podwójne przytoczyć $((...))również. Może to być „trochę” paranoiczne i IFS=0na przykład mało prawdopodobne , ale na pewno nie jest niemożliwe :)
PesaThe
Istnieje również starsza $[[...]]składnia, ale może miałeś rację, zapominając o tym.
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:
Podręcznik Bash ma następującą treść:
źródło
git_prompt
tego gita, sugerują używanie go w ten sposóbPS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
, git zachęta , zgodnie z tym nie powinno działać. Czy jest coś specjalnego wPS#
zmiennych? lub dlaczego to działa, jeśli nie wykonuje interpolacji.PS1
. Spróbujecho $PS1
zobaczyć, co mam na myśli. AlePS1
jest oceniany przed wyświetleniem (zobaczPROMPTING
sekcję na stronie podręcznika bash). Aby to przetestować, spróbujPS1='$X'
. Nie otrzymasz monitu. Następnie uruchomX=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 indeksowanejarr
.Jeśli ustawimy
a następnie
echo
wyrażenie w drugiej kolumnie, otrzymalibyśmy wynik / zachowanie pokazane w trzeciej kolumnie. Czwarta kolumna wyjaśnia zachowanie.Zobacz też:
$''
- GNU Bash Manual$""
- GNU Bash Manualźródło
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
da to:
źródło
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.
Da to:
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.
Da to:
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.
Da to:
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.
Da to:
źródło
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
wtedyecho '$a'
produkuje$a
na standardowej mocy wyjściowej. Natomiastecho "$a"
będzie produkować23
na standardowej mocyźródło
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
Używanie pojedynczych cudzysłowów tutaj jest absolutnie w porządku, ponieważ nie ma potrzeby tutaj zmiennych rozszerzeń, rozważ przypadek
zawiodłoby nieszczęśliwie, ponieważ
$bar
pojedyncze cytaty nie rozszerzyłyby się i należy je podwójnie podać jakoTo powinien być jeden z powodów, dla
$((..))
których zawsze należy rozważyć nad używaniemlet
. Ponieważ w nim zawartość nie jest podzielona na słowa. Poprzedni przykład użycialet
można po prostu zapisać jakoZawsze pamiętaj, aby używać
$((..))
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.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ątrzcurl
instrukcji, aby przekazać licznik za każdym razem, gdy żądanie jest wysyłane, wykonajZwróć 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 dorequestCounter
pola.źródło
$((...))
również. Może to być „trochę” paranoiczne iIFS=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.