Risposte:
`date` si espanderà all'output del date
comando. Tuttavia, rimuove i caratteri di spazio extra nei punti in cui sono presenti più caratteri di spazio consecutivi nell'output. (Questo perché la sostituzione del comando è soggetta alla suddivisione delle parole e dal modo in cui il echo
comando gestisce più argomenti.)
In "` date` " , le virgolette doppie sono virgolette deboli, quindi espandono le variabili (prova" $ PWD ") ed eseguono la sostituzione dei comandi. Il risultato dell'espansione viene passato come singolo argomento al echo
comando, includendo tutti gli spazi consecutivi: vale a dire, la divisione delle parole non viene eseguita.
In `` data '' , le virgolette singole sono virgolette più forti, quindi non consentiranno l'espansione delle variabili o la sostituzione dei comandi al loro interno.
Fare riferimento a questo link per ulteriori spiegazioni.
Modificato il primo punto come correttamente sottolineato da Michael Suelmann nel commento qui sotto .
date
comando bare .
Tutti e due
echo `date`
e
echo "`date`"
visualizzerà la data. L'output di quest'ultimo sembra che l'output funzioni date
da solo.
C'è una differenza, però: quello racchiuso tra "
virgolette "
verrà inviato a echo
come singolo argomento. Le virgolette incapsulano l'output dell'intero comando come un argomento. Dal momento echo
che stampa semplicemente i suoi argomenti in ordine, con spazi nel mezzo, sembrerà sostanzialmente lo stesso.
Ecco un esempio della sottile differenza:
echo `date`
produce:
Fri Nov 1 01:48:45 EST 2013
ma:
echo "`date`"
produce:
Fri Nov 1 01:48:49 EST 2013
Si noti che i due spazi successivi Nov
sono stati ridotti a uno senza virgolette. Questo perché la shell sta analizzando ogni elemento separato da spazio e sta inviando il risultato a eco come 6 argomenti. Quando lo citate, l'eco riceve un singolo argomento e le virgolette mantengono lo spazio.
Questo diventa molto più importante in comandi diversi dall'eco. Ad esempio, immagina un comando foo
che desideri due argomenti: una data e un indirizzo e-mail.
Questo funzionerà in quello scenario:
foo "`date`" joeuser@example.com
Ma questo confonderà lo script inviandolo 7 argomenti:
foo `date` joeuser@example.com
Nelle shell POSIX, `date`
è l'antica forma di sostituzione dei comandi. La sintassi moderna è $(date)
.
In entrambi i casi, si espandono all'output di date
con i caratteri di nuova riga finali eliminati (a condizione che l'output non contenga caratteri NUL).
Tuttavia, quando non è racchiuso tra virgolette doppie e in contesti di elenchi (ad esempio in argomenti a comandi semplici come echo
nel tuo caso), tale espansione è ulteriormente soggetta a:
Suddivisione delle parole : ovvero "l'output di date
con i caratteri di nuova riga finali eliminati" viene suddiviso in base al valore corrente della $IFS
variabile (per impostazione predefinita contenente spazio, tabulazione e nuova riga (e NUL con zsh
)) in più parole .
Ad esempio, se date
le uscite Fri 1 Nov 14:11:15 GMT 2013\n
(come avviene spesso in un locale inglese e in un continente fuso orario britannico), e $IFS
attualmente contiene :
, che sarà suddiviso in 3 parole : Fri 1 Nov 14
, 11
e 15 GMT 2013
.
zsh
): che è, ogni parola derivante dal frazionamento di cui sopra è guardato per i caratteri jolly ( *
, ?
, [...]
anche se alcune conchiglie hanno più), e ampliato l'elenco dei nomi di file che corrispondono a tali modelli. Ad esempio, se l'uscita date
è ?%? 33 */*/* UVC 3432
(come spesso accade nelle zone Venusiane e UVC fuso orario), ed $IFS
è il valore di default), allora che si espande per tutti i non-nascosto 3 nomi carattere nella directory corrente il cui carattere centrale è %
, 33
, tutti i file non nascosti in tutte le sottodirectory non nascoste di tutte le sottodirectory non nascoste della directory corrente UVC
e 3432
.È per questo:
$IFS
i caratteri su cui vuoi dividere.set +f
per disabilitarlo.Le virgolette singole citano tutto, quindi i caratteri di backtick vengono presi alla lettera.
Esempio (l'utilizzo -x
rende più semplice vedere cosa sta succedendo):
$ bash --norc -x
bash-4.2$ IFS=:
+ IFS=:
bash-4.2$ echo `date`
++ date
+ echo 'Fri 1 Nov 14' 42 '33 GMT 2013'
Fri 1 Nov 14 42 33 GMT 2013
bash-4.2$ echo "`date`"
++ date
+ echo 'Fri 1 Nov 14:42:41 GMT 2013'
Fri 1 Nov 14:42:41 GMT 2013
bash-4.2$ cd /lib/modules
+ cd /lib/modules
bash-4.2$ export TZ=UVC LC_ALL=vs_VS
+ export TZ=UVC LC_ALL=vs_VS
+ TZ=UVC
+ LC_ALL=vs_VS
bash-4.2$ unset -v IFS # get the default behaviour
+ unset -v IFS
bash-4.2$ echo `date`
++ date
+ echo '?%?' 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
?%? 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
bash-4.2$ echo "`date`"
++ date
+ echo '?%? 33 */*/* UVC 3432'
?%? 33 */*/* UVC 3432
Se l'output contiene caratteri NUL, il comportamento varia da shell a shell: alcuni li rimuovono, altri troncano l'output al primo carattere NUL, zsh
li conservano ma notano che comunque i comandi esterni non possono accettare argomenti contenenti NUL
Con `date` ottieni l'output della data diviso in più parole, perché la divisione delle parole avviene dopo la sostituzione del comando.
Con "` date` "ottieni l'output di date come una parola / parametro in quanto esiste una sostituzione di comando tra virgolette doppie, ma l'output non viene ulteriormente analizzato. Lo stesso vale con l'espansione variabile come "$ i" nel mio esempio di seguito.
Con '' date` 'ottieni una `data` letterale in quanto non vi è alcuna sostituzione di comando tra virgolette singole.
Forse le differenze delle 3 forme saranno più visibili in questo modo:
> for i in `date`; do echo "$i"; done
Fr
1.
Nov
12:25:30
CET
2013
> for i in "`date`"; do echo "$i"; done
Fr 1. Nov 12:25:38 CET 2013
> for i in '`date`'; do echo "$i"; done
`date`