Mentre prendo il tuo significato, non credo che nessuna di queste risposte sia corretta. eval
non è necessario in alcun modo, né hai nemmeno bisogno di valutare due volte le tue variabili.
È vero, @Gilles si avvicina molto, ma non affronta il problema della possibilità di ignorare i valori e di come dovrebbero essere utilizzati se ne hai bisogno più di una volta. Dopotutto, un modello dovrebbe essere usato più di una volta, giusto?
Penso che sia più importante l'ordine in cui li valuti. Considera quanto segue:
SUPERIORE
Qui imposterai alcune impostazioni predefinite e ti preparerai a stamparle quando viene chiamato ...
#!/bin/sh
_top_of_script_pr() (
IFS="$nl" ; set -f #only split at newlines and don't expand paths
printf %s\\n ${strings}
) 3<<-TEMPLATES
${nl=
}
${PLACE:="your mother's house"}
${EVENT:="the unspeakable."}
${ACTION:="heroin"}
${RESULT:="succeed."}
${strings:="
I went to ${PLACE} and saw ${EVENT}
If you do ${ACTION} you will ${RESULT}
"}
#END
TEMPLATES
MEDIO
Qui è dove si definiscono altre funzioni da chiamare sulla funzione di stampa in base ai loro risultati ...
EVENT="Disney on Ice."
_more_important_function() { #...some logic...
[ $((1+one)) -ne 2 ] && ACTION="remedial mathematics"
_top_of_script_pr
}
_less_important_function() { #...more logic...
one=2
: "${ACTION:="calligraphy"}"
_top_of_script_pr
}
PARTE INFERIORE
Ora hai tutto configurato, quindi ecco dove eseguirai e tirerai i risultati.
_less_important_function
: "${PLACE:="the cemetery"}"
_more_important_function
: "${RESULT:="regret it."}"
_less_important_function
RISULTATI
Esaminerò il perché tra un momento, ma l'esecuzione di quanto sopra produce i seguenti risultati:
_less_important_function()'s
prima corsa:
Sono andato a casa di tua madre e ho visto Disney on Ice.
Se fai calligrafia avrai successo.
poi _more_important_function():
Sono andato al cimitero e ho visto Disney on Ice.
Se fai matematica correttiva ci riuscirai.
_less_important_function()
ancora:
Sono andato al cimitero e ho visto Disney on Ice.
Se fai matematica correttiva te ne pentirai.
COME FUNZIONA:
La caratteristica chiave qui è il concetto di conditional ${parameter} expansion.
È possibile impostare una variabile su un valore solo se non è impostata o è nulla utilizzando il modulo:
${var_name
: =desired_value}
Se invece desideri impostare solo una variabile non impostata, ometteresti i :colon
valori null e rimarrebbero così come sono.
IN CAMPO DI APPLICAZIONE:
Potresti notare che nell'esempio sopra $PLACE
e $RESULT
essere cambiato quando impostato tramite parameter expansion
anche se _top_of_script_pr()
è già stato chiamato, presumibilmente impostandoli quando viene eseguito. Il motivo per cui funziona è che _top_of_script_pr()
è una ( subshelled )
funzione: l'ho racchiusa in un oggetto parens
anziché nell'altro { curly braces }
per gli altri. Poiché viene chiamato in una subshell, ogni variabile che imposta è locally scoped
e quando ritorna alla sua shell padre quei valori scompaiono.
Ma quando _more_important_function()
imposta $ACTION
è globally scoped
così influenza la _less_important_function()'s
seconda valutazione di $ACTION
perché _less_important_function()
imposta $ACTION
solo tramite${parameter:=expansion}.
:NULLO
E perché uso il :colon?
pozzo iniziale, la man
pagina ti dirà che : does nothing, gracefully.
vedi, parameter expansion
è esattamente come suona - expands
al valore del ${parameter}.
So quando impostiamo una variabile con cui ${parameter:=expansion}
rimaniamo con il suo valore - che la shell tenta di eseguire in linea. Se tentasse di eseguirlo, the cemetery
ti sputerebbe degli errori. PLACE="${PLACE:="the cemetery"}"
produrrebbe gli stessi risultati, ma è anche ridondante in questo caso e ho preferito che la shell: ${did:=nothing, gracefully}.
Ti permette di fare questo:
echo ${var:=something or other}
echo $var
something or other
something or other
QUI-DOCUMENTI
E a proposito: la definizione in linea di una variabile nulla o non impostata è anche il motivo per cui:
<<HEREDOC echo $yo
${yo=yoyo}
HEREDOC
yoyo
Il modo migliore per pensare a here-document
è come un file reale trasmesso a un descrittore di file di input. Più o meno è quello che sono, ma conchiglie diverse le implementano in modo leggermente diverso.
In ogni caso, se non citate, lo <<LIMITER
ottenete in streaming e valutato per expansion.
So che una variabile in a here-document
può funzionare, ma solo attraverso ciò expansion
che vi limita a impostare solo variabili che non sono già impostate. Tuttavia, si adatta perfettamente alle tue esigenze come le hai descritte, poiché i valori predefiniti verranno sempre impostati quando chiami la funzione di stampa del modello.
PERCHÈ NO eval?
Bene, l'esempio che ho presentato fornisce un mezzo sicuro ed efficace per accettare. parameters.
Poiché gestisce l'ambito, ogni variabile all'interno di set via ${parameter:=expansion}
è definibile dall'esterno. Quindi, se metti tutto questo in uno script chiamato template_pr.sh ed esegui:
% RESULT=something_else template_pr.sh
Otterresti:
Sono andato a casa di tua madre e ho visto Disney on Ice
Se fai la calligrafia, farai qualcosa
Sono andato al cimitero e ho visto Disney on Ice
Se fai matematica correttiva, farai qualcosa
Sono andato al cimitero e ho visto Disney on Ice
Se fai matematica correttiva, farai qualcosa
Questo non funzionerebbe per quelle variabili che sono state letteralmente impostate nello script, come $EVENT, $ACTION,
e $one,
ma ho definito solo quelle in quel modo per dimostrare la differenza.
In ogni caso, l'accettazione di input sconosciuti in evaled
un'istruzione è intrinsecamente pericolosa, mentre parameter expansion
è specificamente progettata per farlo.