Jaka jest różnica między cudzysłowami „…”, „…”, $ „…” i $ „…”?


49

Czasem widzę skrypty używać wszystkich tych różnych sposobów cytuje tekst: "...", '...', $'...', i $"...". Dlaczego stosuje się tak wiele różnych rodzajów ofert?

Czy zachowują się inaczej lub wpływają na to, co mogę w nich zrobić?


1
Możliwe duplikaty między witrynami. Ta odpowiedź zawiera podsumowanie (lub łącza do) semantyki wszystkich różnych rodzajów cytatów.
chepner

Odpowiedzi:


66

Wszystko to oznacza coś innego i możesz pisać w nich różne rzeczy (lub te same rzeczy, o innym znaczeniu). Różne rodzaje cytatów interpretują różne sekwencje specjalne w nich ( \something), lub dopuszczają lub nie pozwalają na interpolacje zmienne ( $something) i inne rodzaje interpretacji w nich.

W skrócie:

  • '...' jest całkowicie dosłowny.
  • "..." dopuszcza zarówno zmienne, jak i osadzone znaki cudzysłowu.
  • $'...'wykonuje znaki ucieczki jak \n, ale nie rozwija zmiennych.
  • $"..." jest dla tłumaczeń na język ludzki w języku Bash i ksh.

'Pojedyncze cytaty'

Cokolwiek piszesz między pojedynczymi cudzysłowami, jest traktowane dosłownie i wcale nie przetwarzane. Odwrotne ukośniki i znaki dolara nie mają tutaj specjalnego znaczenia. Oznacza to, że nie można uciec od znaku odwrotnego ukośnika (w tym innych pojedynczych cudzysłowów!), Interpolować zmiennej lub użyć innej funkcji powłoki.

Wszystkie te przykłady dają dosłownie to, co jest napisane między cytatami:

'hello world'                     => hello world
'/pkg/bin:$PATH'                  => /pkg/bin:$PATH
'hello\nworld'                    => hello\nworld
'`echo abc`'                      => `echo abc`
'I\'dn\'t've'                     => I\dn'tve

Ostatni jest skomplikowany - istnieją dwa ciągi pojedynczego cudzysłowu wraz z niecytowanym tekstem. Pierwszy zawiera I\. Niecytowany tekst dn\'tzawiera pojedynczy cudzysłów, który jest usuwany na poziomie powłoki , więc nie zaczyna cytowanego łańcucha i jest zawarty jako dosłowny znak (więc, dn't). Ostatni cytowany ciąg jest sprawiedliwy ve. Wszystkie zbiegają się w jedno słowo w zwykły sposób, w jaki działa powłoka.

Dość powszechnym idiomem łączącym dosłowny tekst i zmienne jest ich łączenie w następujący sposób:

'let x="'$PATH\"

spowoduje

let x="/usr/bin:/bin"

jako pojedyncze słowo (lepiej też podwójnie zacytować $PATHna wszelki wypadek - spacje lub znaki globowania w wartości zmiennej mogą być przetwarzane inaczej - ale ze względu na czytelny przykład, którego nie zrobiłem).


„Podwójne cudzysłowy”

Wewnątrz podwójnych cudzysłowów przetwarzane są dwa rodzaje rozwinięć i można użyć ukośnika odwrotnego do znaków specjalnych, aby zapobiec przetwarzaniu rozszerzeń lub znaków ucieczki.

Istnieją dwie kategorie rozwinięć, które występują w podwójnych cudzysłowach:

W cudzysłowie odwrotny ukośnik może zahamować te rozszerzenia, umieszczając go przed znakiem $lub `. Może również uniknąć podwójnego cudzysłowu zamykającego, więc \"zawiera tylko "w ciągu lub innym odwrotnym ukośnikiem. Wszelkie inne ukośniki odwrotne są zachowywane dosłownie - nie ma znaków ucieczki w celu wytworzenia innych znaków i nie jest usuwane.

Niektóre z tych przykładów działają inaczej niż wcześniej, a niektóre nie:

"hello world"                     => hello world
"/pkg/bin:$PATH"                  => /pkg/bin:/bin:/usr/bin
"hello\nworld"                    => hello\nworld
"hello\\nworld"                   => hello\nworld
"`echo abc`"                      => abc
"I\'dn\'t've"                     => I\'dn\'t've
"I'dn't've"                       => I'dn't've
"I\"dn\"t've"                     => I"dn"t've

$ „ANSI-C notowania”

Ten rodzaj cytowania pozwala na przetwarzanie znaków odwrotnego ukośnika w stylu C, ale nie osadzonych zmiennych ani podstawień. To jedyny rodzaj cytowania, który obsługuje ucieczki postaci .

Jest to rozszerzenie od ksh, teraz obsługiwane również w Bash, zsh i niektórych innych powłokach. Nie jest jeszcze częścią standardu POSIX, więc maksymalnie przenośne skrypty nie mogą go używać, ale skrypt Bash lub ksh jest darmowy.

Wszystkie z tych ucieczek może być używany z ich znaczeniami c: \a, \b, \f, \n, \r, \t, \v, a dosłownych ucieczek \\, \', \", i \?. Obsługują również rozszerzenia \e(znak ucieczki) oraz w Bash i ksh \cx(to, co byłoby wprowadzone przez Ctrl-x , np. \cMPowrót karetki). Pociski mają szereg własnych niewielkich rozszerzeń.

Pozwala także na cztery rodzaje ogólnych ucieczek postaci:

  • \nnn, jeden bajt o wartości ósemkowej nnn
  • \xHH, jeden bajt o wartości szesnastkowej HH
  • \uHHHH, punkt kodowy Unicode, którego indeksem szesnastkowym jest HHHH
  • \UHHHHHHHH, punkt kodowy Unicode, którego indeksem szesnastkowym jest HHHHHHHH

Wszystkie te cyfry są opcjonalne po pierwszej.

$i `nie mają żadnego znaczenia i są zachowane dosłownie, więc nie możesz tam dołączyć zmiennej.

$'hello world'                    => hello world
$'/pkg/bin:$PATH'                 => /pkg/bin:$PATH
$'hello\nworld'                   => hello
                                     world
$'`echo abc`'                     => `echo abc`
$'I\'dn\'t\'ve'                   => I'dn't've
$'\U1f574\u263A'                  => 🕴☺

Większość z tych ucieczek można symulować za pomocą na printfkomendę , choć POSIX wymaga jedynie \\, \a, \b, \f, \n, \r, \t, \v, i \nnntam pracować. Można użyć podstawienia polecenia osadzić printfwewnątrz cudzysłowów w razie potrzeby: "Path:$(printf '\t')$PATH".


$ „Tłumaczenie regionalne”

Jest to rozszerzenie specyficzne dla ksh i Bash do lokalizowania ciągów tekstowych w języku naturalnym i wyszukuje część wewnątrz cytatów w katalogu komunikatów. Najpierw wykonuje wszystkie rozszerzenia podwójnego cudzysłowu. Jeśli ciąg nie zostanie znaleziony w bazie danych tłumaczeń, zostanie użyty jako własne tłumaczenie. Wbudowane założenie jest takie, że ciągi są w języku angielskim.

Prawdopodobnie nie chcesz go używać, ale jeśli go widzisz, możesz ogólnie traktować go jako zwykłe podwójne cudzysłowy.


Należy zwrócić uwagę na to, że nie istnieje żaden cytat, który umożliwia zarówno rozszerzenie parametrów osadzonych, jak i znaki ucieczki osadzonych znaków. W większości przypadków, gdy tego chcesz, lepiej (bezpieczniej) skorzystać z printf:

printf 'New path: \e[1m%s\e[0m' "/pkg/bin:$PATH:"

Wyraźnie oddziela to, które części podlegają zmianie znaku, a które wartości danych.

Innym jest to, że wszystkie te style cytowania tworzą pojedyncze „słowo” w powłoce, chyba że wewnątrz podwójnych cudzysłowów zastosowano $@rozszerzenie tablicy ${x[@]}. Obie formy pojedynczych cytatów są zawsze jednym słowem i nigdy nie są dalej rozwijane.


$"..."jest również z ksh93, dodany do bash w 2.0.
Stéphane Chazelas

Nie ma \cXw zsh. Jest \CXalbo \C-Xtam ( \cma już specjalne znaczenie echo)
Stéphane Chazelas

'let x="'$PATH\"jest źle w kontekstach lista w muszli innych niż zshjak $PATHnie jest notowany (tak podlegałyby podzielone + glob, który nie chciałby tutaj).
Stéphane Chazelas

Możesz wyjaśnić, że mówisz o muszlach podobnych do Korna, przetwarzanie cytatów jest inne w csh, rc, fish ...
Stéphane Chazelas

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.