Risposte:
Le virgolette singole non interpolano nulla, ma le virgolette doppie lo fanno. Ad esempio: variabili, backtick, determinate \
escape, ecc.
Esempio:
$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")
Il manuale di Bash ha questo da dire:
Racchiudere i caratteri tra virgolette singole (
'
) conserva il valore letterale di ciascun carattere tra virgolette. Una virgoletta singola potrebbe non verificarsi tra virgolette singole, anche se preceduta da una barra rovesciata.Racchiudere caratteri tra virgolette (
"
) conserva il valore letterale di tutti i caratteri all'interno delle virgolette, ad eccezione di$
,`
,\
e, quando l'espansione della cronologia è abilitata,!
. I personaggi$
e`
mantengono il loro significato speciale tra virgolette (vedi Espansioni della shell ). Il backslash mantiene il suo significato speciale solo quando seguito da uno dei seguenti caratteri:$
,`
,"
,\
o newline. Tra virgolette doppie, le barre rovesciate seguite da uno di questi caratteri vengono rimosse. Le barre rovesciate che precedono i caratteri senza un significato speciale vengono lasciate non modificate. Una virgoletta doppia può essere citata tra virgolette precedenti precedendola con una barra rovesciata. Se abilitato, l'espansione della cronologia verrà eseguita a meno che non!
venga evitato di apparire tra virgolette usando una barra rovesciata. La barra rovesciata che precede il!
non viene rimossa.I parametri speciali
*
e@
hanno un significato speciale quando tra virgolette (vedi Shell parametro di espansione ).
git_prompt
che git fornisce loro suggeriscono di usarlo in questo modo PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
, git prompt , in base a ciò non dovrebbe funzionare. C'è qualcosa di speciale nelle PS#
variabili? o perché funziona se non sta eseguendo l'interpolazione.
PS1
. Prova echo $PS1
a capire cosa intendo. Ma PS1
viene valutato prima di essere visualizzato (vedere la PROMPTING
sezione nella manpage di bash). Per provarlo, prova PS1='$X'
. Non avrai nessun prompt. Quindi esegui X=foo
e improvvisamente il tuo prompt è "pippo" ( PS1
valutato se impostato invece di visualizzato non avresti ancora alcun prompt).
La risposta accettata è ottima. Sto preparando un tavolo che aiuta a comprendere rapidamente l'argomento. La spiegazione riguarda una variabile semplice a
e una matrice indicizzata arr
.
Se impostiamo
a=apple # a simple variable
arr=(apple) # an indexed array with a single element
e quindi echo
l'espressione nella seconda colonna, otterremmo il risultato / comportamento mostrato nella terza colonna. La quarta colonna spiega il comportamento.
# | 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
---+-------------+-------------+--------------------------------------------------------------------
Guarda anche:
The special parameters * and @ have special meaning when in double quotes
quindi come mai i "*"
risultati *
?
"$@"
e "$*"
sono espansioni di parametri. "@"
e "*"
non lo sono.
echo "\'"
mi restituisce \'
.
Se ti riferisci a ciò che accade quando fai eco a qualcosa, le virgolette singole fanno letteralmente eco a ciò che hai tra loro, mentre le virgolette doppie valutano le variabili tra loro e generano il valore della variabile.
Ad esempio, questo
#!/bin/sh
MYVAR=sometext
echo "double quotes gives you $MYVAR"
echo 'single quotes gives you $MYVAR'
darà questo:
double quotes gives you sometext
single quotes gives you $MYVAR
Altri hanno spiegato molto bene e vogliono solo dare esempi semplici.
Virgolette singole possono essere usate attorno al testo per impedire alla shell di interpretare caratteri speciali. Segni di dollaro, spazi, e commerciali, asterischi e altri caratteri speciali sono tutti ignorati se racchiusi tra virgolette singole.
$ echo 'All sorts of things are ignored in single quotes, like $ & * ; |.'
Darà questo:
All sorts of things are ignored in single quotes, like $ & * ; |.
L'unica cosa che non può essere inserita tra virgolette singole è una virgoletta singola.
Le virgolette doppie funzionano in modo simile alle virgolette singole, ad eccezione delle virgolette doppie che consentono comunque alla shell di interpretare i simboli del dollaro, le virgolette posteriori e le barre rovesciate. È già noto che le barre rovesciate impediscono l'interpretazione di un singolo carattere speciale. Questo può essere utile tra virgolette se un simbolo di dollaro deve essere usato come testo anziché per una variabile. Consente inoltre di evitare le virgolette doppie in modo che non vengano interpretate come la fine di una stringa tra virgolette.
$ echo "Here's how we can use single ' and double \" quotes within double quotes"
Darà questo:
Here's how we can use single ' and double " quotes within double quotes
Si può anche notare che l'apostrofo, che sarebbe altrimenti interpretato come l'inizio di una stringa tra virgolette, viene ignorato tra virgolette doppie. Le variabili, tuttavia, vengono interpretate e sostituite con i loro valori tra virgolette doppie.
$ echo "The current Oracle SID is $ORACLE_SID"
Darà questo:
The current Oracle SID is test
Le virgolette posteriori sono completamente diverse dalle virgolette singole o doppie. Invece di essere utilizzati per impedire l'interpretazione di caratteri speciali, le virgolette in realtà forzano l'esecuzione dei comandi che racchiudono. Dopo aver eseguito i comandi allegati, il loro output viene sostituito al posto delle virgolette posteriori nella riga originale. Ciò sarà più chiaro con un esempio.
$ today=`date '+%A, %B %d, %Y'`
$ echo $today
Darà questo:
Monday, September 28, 2015
Esiste una chiara distinzione tra l'uso di ' '
e " "
.
Quando ' '
viene utilizzato attorno a qualsiasi cosa, non viene eseguita alcuna "trasformazione o traduzione". Viene stampato così com'è.
Con " "
, qualunque cosa circonda, viene "tradotto o trasformato" nel suo valore.
Per traduzione / trasformazione intendo quanto segue: Qualsiasi cosa tra virgolette singole non verrà "tradotta" nei loro valori. Saranno presi come sono tra virgolette. Esempio:, a=23
quindi echo '$a'
produrrà $a
su output standard. Considerando echo "$a"
che produrrà 23
sulla produzione standard.
Poiché questa è la risposta di fatto quando si tratta di virgolette bash
, aggiungerò un altro punto mancante nelle risposte sopra, quando si tratta degli operatori aritmetici nella shell.
La bash
shell supporta due modi per eseguire operazioni aritmetiche, una definita dal let
comando integrato e $((..))
dall'operatore. Il primo valuta un'espressione aritmetica mentre il secondo è più un'istruzione composta.
È importante capire che l'espressione aritmetica usata con let
subisce l'espansione del frazionamento delle parole, proprio come qualsiasi altro comando shell. Pertanto, è necessario eseguire una corretta quotazione e fuga.
Vedi questo esempio durante l'utilizzo let
let 'foo = 2 + 1'
echo $foo
3
L'uso di virgolette singole qui è assolutamente perfetto qui, poiché non è necessario per espansioni variabili qui, prendere in considerazione un caso di
bar=1
let 'foo = $bar + 1'
fallirebbe miseramente, poiché le $bar
virgolette singole sottostanti non si espandono e devono essere racchiuse tra virgolette
let 'foo = '"$bar"' + 1'
Questo dovrebbe essere uno dei motivi, $((..))
dovrebbe essere sempre considerato oltre l'utilizzo let
. Perché al suo interno, i contenuti non sono soggetti a suddivisione in parole. L'esempio precedente usando let
può essere semplicemente scritto come
(( bar=1, foo = bar + 1 ))
$((..))
senza virgolette singoleSebbene $((..))
possa essere utilizzato con virgolette doppie, non vi è alcun motivo in quanto non può contenere un contenuto che avrebbe bisogno della virgoletta doppia. Assicurati solo che non sia quotato singolarmente.
printf '%d\n' '$((1+1))'
-bash: printf: $((1+1)): invalid number
printf '%d\n' $((1+1))
2
printf '%d\n' "$((1+1))"
2
In alcuni casi speciali di utilizzo $((..))
dell'operatore all'interno di una singola stringa tra virgolette, potrebbe essere necessario interpolare le virgolette in modo tale che l'operatore rimanga senza virgolette o tra virgolette doppie. Ad esempio, prendere in considerazione un caso, quando si sta tentando di utilizzare l'operatore all'interno di curl
un'istruzione per passare un contatore ogni volta che viene effettuata una richiesta, fare
curl http://myurl.com --data-binary '{"requestCounter":'"$((reqcnt++))"'}'
Notare l'uso di virgolette doppie nidificate all'interno, senza le quali la stringa letterale $((reqcnt++))
viene passata al requestCounter
campo.
$((...))
pure. Potrebbe essere "un po '" paranoico e abbastanza improbabile, ad IFS=0
esempio, ma certamente non è impossibile :)
$[[...]]
sintassi legacy, ma forse avevi ragione a dimenticarla.