Perché l'espansione della variabile bash mantiene le virgolette?


12
> echo "hi"
hi
> VAR='echo "hi"'
> $VAR
"hi"

Perché l'output dei comandi precedenti è diverso?

Una cosa simile si verifica con virgolette singole:

> VAR="echo 'hi'"
> $VAR
> 'hi'

6
Non prendere l'abitudine di incorporare frammenti di script eseguibili in variabili. Questo tende ad essere al massimo complicato ed evalè un campo minato di potenziali buchi di sicurezza che devi percorrere con molta attenzione
jw013,

@ jw013 Un buon punto e ottimi articoli. Mi piace la frase "Le variabili contengono dati, le funzioni contengono codice". dal primo collegamento, ma per il mio utilizzo, i dati forniti a una funzione (in questo caso at) è il codice. Qualche suggerimento su un modo più sicuro di organizzare / raccogliere il codice a cui verrà dato at?
Cory Klein,

ataccetta la shsintassi come input. Quindi generare input per atsignifica generare una shsintassi valida, opportunamente quotata da input arbitrario, il che non è banale, quindi proverei ad evitarlo se possibile. Sarebbe davvero utile se potessi dare un po 'più di dettagli su ciò che stai cercando di realizzare.
jw013,

Scusa, non volevo distrarmi con troppi dettagli, ma quello che sto facendo non è molto complicato, IMO. Sto creando uno script che richiede un "tempo" e un "messaggio". Quindi viene eseguito atper il "tempo" specificato e indica atdi eseguire il comando dzen2. dzen2prende il "messaggio" da stdin e usa anche altri parametri statici. La difficoltà è che devo reindirizzare il parametro "message" dall'utente al dzen2comando, ma in realtà non sto eseguendo dzen2me stesso, sto dicendo atdi farlo.
Cory Klein,

Risposte:


16

La coppia aggiuntiva di virgolette verrebbe consumata solo da una fase di valutazione aggiuntiva. Ad esempio forzato da eval:

bash-4.2$ VAR='echo "hi"'

bash-4.2$ $VAR
"hi"

bash-4.2$ eval $VAR
hi

Ma in genere è una cattiva idea inserire comandi con parametri in una stringa. Utilizzare invece un array:

bash-4.2$ VAR=(echo "hi")

bash-4.2$ "${VAR[@]}"
hi

1
È anche importante notare che le virgolette vengono valutate in modo diverso; le virgolette doppie (") consentono la valutazione della stringa racchiusa, le virgolette singole (') stampano la stringa come un valore letterale. Esempio: "$(ls)"e '$(ls)'. Questo è il motivo per cui le virgolette compaiono negli esempi di domande originali.
Joseph Kern,

Un array è anche fonte di problemi. Il codice appartiene alle funzioni, i dati alle variabili. L'esempio presentato funziona solo perché le virgolette vengono rimosse nella divisione dell'array. A printf '<%s> ' "${VAR[@]}"mostrerà che le virgolette sono già state rimosse. Se si imposta VAR VAR=(echo \"hi\")in modo che abbia effettivamente le virgolette, lo stesso problema appare di nuovo, $ ${VAR[@]}verrà stampato"hi"


2

Se fai un passo indietro, puoi capire perché la sostituzione delle variabili dovrebbe assolutamente conservare le virgolette.

Il punto di virgolette in una shell Unix / Linux / BSD è di tenere insieme pezzi di una stringa che altrimenti verrebbero analizzati come più stringhe. Poiché per impostazione predefinita una shell utilizza gli spazi bianchi come separatore di token, una stringa con spazi (come "uno due tre") se non citata o evasa in qualche modo, verrebbe analizzata come 3 stringhe: "uno", "due" e "tre".

Se un programmatore desidera una stringa con il valore di una variabile interpolata:

VAR=two
STRING="one $VAR three"

la shell non dovrebbe assolutamente rimuovere le virgolette: la stringa contenente spazi verrebbe analizzata come 3 stringhe più piccole.

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.