Perché non questo codice bash lavoro?
Domanda
x="a=b"
`echo $x`
echo $a
mi aspetto la seconda linea di generare "a = b", ed eseguirlo nel contesto del guscio principale, risultando in un nuovo a
variabile con valore b
.
Tuttavia, ciò che proprio mi piace (se entro i comandi manualmente) è il messaggio di errore dopo la seconda linea, bash: a=b: command not found
Perché è così?
Soluzione
E 'a causa del l'ordine in cui bash analizza la riga di comando. Sembra per la definizione di variabili (ad esempio a=b
) prima eseguendo variabile e sostituzione di comando (ad esempio comandi backticks). A causa di questo, dal echo $x
tempo viene sostituito da a=b
, è troppo tardi per bash per vedere questo come definizione della variabile ed è analizzato come un comando, invece. La stessa cosa sarebbe successo se avessi appena usato $x
come il comando (al posto di eco in apici inversi). Come in @ risposta di MVDS, il comando eval
può essere usato per forzare il comando da reparsed fin dall'inizio, il che significa che sarà riconosciuto come una definizione di variabile:
$ x="a=b"
$ `echo $x`
-bash: a=b: command not found
$ $(echo $x) # Exact same thing, but with cleaner syntax
-bash: a=b: command not found
$ $x # This also does the same thing, but without some extra steps
-bash: a=b: command not found
$ eval "$x" # This will actually work
$ echo $a
b
$ a= # Start over
$ eval "$(echo "$x")" # Another way of doing the same thing, with extra steps
$ echo $a
b
Si noti che quando si utilizza eval
ho messo tutti i riferimenti a $x
tra virgolette - questo è quello di evitare che le fasi successive di bash analisi (ad es splitting parola) accada due volte , poiché bash si concluderà il suo processo di analisi regolare, quindi riconosce il comando eval
, e quindi ripetere l'intero processo di analisi nuovo . E 'davvero facile per ottenere risultati inaspettati dal usando eval
, e questo rimuove almeno alcuni del potenziale di guai.
Altri suggerimenti
Prova
eval $x
(E abbiamo bisogno di 30 caratteri per questa risposta per essere pubblicato)
Che la prima linea eco fa è in esecuzione in una subshell e restituisce il suo valore al chiamato .. Lo stesso risultato si ottiene utilizzando $()
ed è - tra l'altro -. Più facile da usare rispetto backticks
Quindi, quello che stai facendo è prima esecuzione echo $x
(che restituisce a=b
). E, a causa degli apici inversi, a=b
viene restituito alla shell che cerca di correre quella linea come un comando che - ovviamente -. Non funzionerà
Prova questo in un guscio:
$(echo ls)
E vedrete chiaramente che cosa sta accadendo.
Hai provato $x
fatto che i apostrofi divertenti? Senza echo
, eco sembra essere solo per la visualizzazione di stringa, non eseguire i comandi.