Qual è la differenza tra le virgolette "...", "...", $ "..." e $ "..."?


49

A volte vedo script usano tutti questi diversi modi di citare un testo: "...", '...', $'...', e $"...". Perché ci sono così tanti diversi tipi di preventivo utilizzati?

Si comportano diversamente o influenzano ciò che posso fare al loro interno?


1
Possibile duplicato tra siti. Questa risposta fornisce un riepilogo (o collegamenti a) la semantica di tutti i diversi tipi di virgolette.
Chepner,

Risposte:


66

Tutti questi significano qualcosa di diverso e puoi scrivere cose diverse al loro interno (o le stesse cose, con significato diverso). Diversi tipi di citazione interpretano diverse sequenze di escape al loro interno ( \something) o consentono o non consentono interpolazioni variabili ( $something) e altri tipi di espansione al loro interno.

In breve:

  • '...' è del tutto letterale.
  • "..." consente sia variabili che caratteri di citazione incorporati.
  • $'...'esegue le escape di caratteri come \n, ma non espande le variabili.
  • $"..." è per le traduzioni in lingua umana in Bash e ksh.

"Virgolette singole"

Qualunque cosa tu scriva tra virgolette singole viene trattata letteralmente e non elaborata affatto. Le barre rovesciate e i segni del dollaro non hanno un significato speciale lì. Ciò significa che non è possibile eseguire il backslash-escape di un personaggio (incluse altre virgolette singole!), Interpolare una variabile o utilizzare qualsiasi altra funzione della shell.

Tutti questi esempi danno come risultato letteralmente ciò che è scritto tra virgolette:

'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

L'ultima è complicata: ci sono due stringhe a virgoletta singola eseguite insieme a del testo non quotato. Il primo contiene I\. Il testo non quotato dn\'tcontiene una singola citazione che è sfuggita a livello di shell , quindi non inizia una stringa tra virgolette ed è inclusa come carattere letterale (quindi, dn't). L'ultima stringa tra virgolette è giusta ve. Tutti quelli si incontrano in una sola parola nel solito modo in cui funziona la shell.

Un linguaggio un po 'comune per combinare testo e variabili letterali è eseguirli insieme in questo modo:

'let x="'$PATH\"

si tradurrà in

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

come una singola parola (è meglio fare una doppia virgoletta $PATHanche nel caso in cui - gli spazi o i caratteri globbing nel valore della variabile possano essere elaborati altrimenti - ma per il bene di un esempio corrente leggibile non l'ho fatto).


"Virgolette"

All'interno delle doppie virgolette, vengono elaborati due tipi di espansione ed è possibile utilizzare una barra rovesciata per sfuggire ai caratteri per impedire l'elaborazione di espansioni o fughe.

Esistono due categorie di espansione tra virgolette doppie:

All'interno delle virgolette, una barra rovesciata può inibire quelle espansioni mettendola prima del $o `. Può anche sfuggire a una doppia virgoletta di chiusura, quindi \"include solo "la stringa o un'altra barra rovesciata. Qualsiasi altra barra rovesciata viene preservata letteralmente: non ci sono fughe per produrre altri personaggi e non viene rimossa.

Alcuni di questi esempi si comportano in modo diverso rispetto a prima, altri no:

"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

$ 'Quotazione ANSI-C'

Questo tipo di quotazione consente di elaborare gli escape backslash in stile C, ma non le variabili o le sostituzioni incorporate. È l' unico tipo di citazione che supporta le fughe di caratteri .

Questa è un'estensione di ksh, ora supportata anche in Bash, zsh e in alcune altre shell. Non fa ancora parte dello standard POSIX e quindi gli script con la massima portabilità non possono usarlo, ma uno script Bash o ksh è gratuito.

Tutte queste fughe può essere utilizzato con i loro significati C: \a, \b, \f, \n, \r, \t, \v, e le fughe letterali \\, \', \", e \?. Supportano anche le estensioni \e(carattere di escape) e in Bash e ksh \cx(ciò che verrebbe inserito da Ctrl-x , ad es. \cMÈ il ritorno a capo). Le conchiglie hanno una gamma di estensioni minori.

Inoltre, consente quattro tipi di escape di caratteri generici:

  • \nnn, un singolo byte con valore ottale nnn
  • \xHH, un singolo byte con valore esadecimale HH
  • \uHHHH, il punto di codice Unicode il cui indice esadecimale è HHHH
  • \UHHHHHHHH, il punto di codice Unicode il cui indice esadecimale è HHHHHHHH

Tutte queste cifre sono opzionali dopo la prima.

$e `non hanno alcun significato e vengono conservati letteralmente, quindi non è possibile includere una variabile lì.

$'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'                  => 🕴☺

La maggior parte di queste fughe si può simulare con il printfcomando , anche se POSIX richiede solo \\, \a, \b, \f, \n, \r, \t, \v, e \nnnal lavoro lì. È possibile utilizzare la sostituzione di comando per incorporare un printfvirgolette dentro se necessario: "Path:$(printf '\t')$PATH".


$ "Traduzione locale"

Questa è un'estensione specifica per ksh e Bash per localizzare stringhe testuali in linguaggio naturale e cerca la parte all'interno delle virgolette in un catalogo di messaggi. Esegue prima tutte le espansioni di virgolette doppie. Se la stringa non viene trovata nel database di traduzione, viene utilizzata come traduzione propria. Il presupposto incorporato è che le stringhe sono in inglese.

Probabilmente non vuoi usare questo, ma se lo vedi puoi generalmente trattarlo come doppie virgolette regolari.


Un punto da notare è che non esiste alcun tipo di quotazione che consenta sia l'espansione dei parametri incorporata sia l'escape dei caratteri incorporati. Nella maggior parte dei casi in cui lo vorresti, sarebbe meglio (più sicuro) usare printf:

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

Ciò separa chiaramente quali parti sono soggette alla fuga di caratteri e quali sono i valori dei dati.

Un altro è che tutti questi stili di quotazione creano una singola "parola" nella shell, a meno $@ che non venga utilizzata o un'espansione dell'array ${x[@]}tra virgolette doppie. Entrambi i moduli a virgoletta singola sono sempre una parola e non si espandono più.


$"..."viene anche da ksh93, aggiunto a bash in 2.0.
Stéphane Chazelas,

Non c'è \cXdentro zsh. È \CXo \C-Xlì ( \cha già un significato speciale in echo)
Stéphane Chazelas il

'let x="'$PATH\"è errato nei contesti di elenco nelle shell diverse da zshcome $PATHnon è citato (quindi sarebbe soggetto a split + glob che non vorresti qui).
Stéphane Chazelas,

Potresti voler chiarire che stai parlando di conchiglie simili a Korn, l'elaborazione delle citazioni è diversa in csh, rc, fish ...
Stéphane Chazelas

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.