Qual è la differenza tra echo `date`, echo“ `date`” e echo '`date`'?


23

Qual è la differenza tra questi tre comandi?

echo `date`
echo "`date`"
echo '`date`'

Sono confuso su quali siano le differenze. Penso che quando 'sono intorno significa che è una stringa, quindi l'eco produrrà letteralmente la stringa dateinvece di visualizzare la data?

Risposte:


19

`date` si espanderà all'output del datecomando. 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 echocomando 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 echocomando, 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 .


1
Come si chiama esattamente il carattere che viene chiamato data circostante? Se ho capito bene, i meta caratteri non funzioneranno tra virgolette singole?
Giovanni

Se ho capito bene, i meta caratteri non funzioneranno tra virgolette singole?
Giovanni

8
Il `viene spesso chiamato" backtick "in quello scenario e in vari documenti / documentazione Unix. In realtà non viene utilizzato come accento grave Unicode quando è da solo in quel modo, anche se questo è il nome del simbolo. E hai ragione che non si verificherà alcuna espansione di metacaratteri / espressioni se lo circondi con virgolette singole.
Jim Stewart,

La tua prima affermazione non è corretta poiché l'output potrebbe essere leggermente diverso a seconda della data o delle impostazioni internazionali. Solo il secondo comando genererà la stessa cosa del datecomando bare .
jlliagre,

1
@BonsiScott Lo spazio aggiuntivo tra "Nov" e "1" viene rimosso anche in HTML;)
Izkata

16

Tutti e due

echo `date`

e

echo "`date`"

visualizzerà la data. L'output di quest'ultimo sembra che l'output funzioni dateda solo.

C'è una differenza, però: quello racchiuso tra "virgolette "verrà inviato a echocome singolo argomento. Le virgolette incapsulano l'output dell'intero comando come un argomento. Dal momento echoche 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 Novsono 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 fooche 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

3
Sei contraddittorio nella tua prima frase. Il primo e il secondo modulo non genereranno sempre la stessa cosa mostrata in seguito.
jlliagre,

Grazie. Ho modificato il testo per renderlo più chiaro.
Jim Stewart,

3

Nelle shell POSIX, `date`è l'antica forma di sostituzione dei comandi. La sintassi moderna è $(date).

In entrambi i casi, si espandono all'output di datecon 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 echonel tuo caso), tale espansione è ulteriormente soggetta a:

  1. Suddivisione delle parole : ovvero "l'output di datecon i caratteri di nuova riga finali eliminati" viene suddiviso in base al valore corrente della $IFSvariabile (per impostazione predefinita contenente spazio, tabulazione e nuova riga (e NUL con zsh)) in più parole .

    Ad esempio, se datele 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 $IFSattualmente contiene :, che sarà suddiviso in 3 parole : Fri 1 Nov 14, 11e 15 GMT 2013.

  2. Nome file generazione (aka globbing ) (se non con 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 UVCe 3432.

È per questo:

  1. Dovresti sempre citare (con virgolette doppie) sostituzioni di comandi a meno che tu non voglia eseguire la divisione della parola o la generazione del nome del file eseguita al momento della sua espansione
  2. Se vuoi dividere le parole , allora dovresti impostare $IFSi caratteri su cui vuoi dividere.
  3. Se si desidera la suddivisione delle parole ma non la generazione del nome file , è necessario emettere un set +fper disabilitarlo.

Le virgolette singole citano tutto, quindi i caratteri di backtick vengono presi alla lettera.

Esempio (l'utilizzo -xrende 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, zshli conservano ma notano che comunque i comandi esterni non possono accettare argomenti contenenti NUL


Non esiste una vera "shell POSIX". Ci sono shell che possono conformarsi ai vari standard POSIX rilevanti usando un sottoinsieme limitato della loro funzionalità.
fpmurphy

0

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`
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.