Ho scritto una sceneggiatura che può generare questi argomenti per me, con virgolette
Se l'output è quotato correttamente per la shell e ti fidi dell'output , puoi eseguirlo eval
.
Supponendo che tu abbia una shell che supporti gli array, sarebbe meglio usarne uno per memorizzare gli argomenti che ottieni.
Se ./gen_args.sh
produce un output simile 'foo bar' '*' asdf
, allora potremmo eseguire eval "args=( $(./gen_args.sh) )"
per popolare un array chiamato args
con i risultati. Questo sarebbe i tre elementi foo bar
, *
, asdf
.
Possiamo usare "${args[@]}"
come al solito per espandere singolarmente gli elementi dell'array:
$ eval "args=( $(./gen_args.sh) )"
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
(Notare le virgolette. Si "${array[@]}"
espande a tutti gli elementi come argomenti distinti non modificati. Senza virgolette gli elementi dell'array sono soggetti alla suddivisione delle parole. Vedere ad esempio la pagina Array su BashGuide .)
Tuttavia , eval
eseguirà felicemente qualsiasi sostituzione della shell, quindi $HOME
nell'output si espanderà nella directory home e una sostituzione di comando eseguirà effettivamente un comando nella shell in esecuzione eval
. Un output di "$(date >&2)"
creerebbe un singolo elemento array vuoto e stamperebbe la data corrente su stdout. Questa è una preoccupazione se si gen_args.sh
ottengono i dati da una fonte non attendibile, come un altro host in rete, nomi di file creati da altri utenti. L'output potrebbe includere comandi arbitrari. (Se di per get_args.sh
sé era dannoso, non avrebbe bisogno di emettere nulla, poteva semplicemente eseguire direttamente i comandi dannosi.)
Un'alternativa alla quotazione della shell, che è difficile da analizzare senza valutazione, sarebbe quella di usare qualche altro personaggio come separatore nell'output del tuo script. Dovresti sceglierne uno che non è necessario negli argomenti reali.
Scegliamo #
e abbiamo l'output dello script foo bar#*#asdf
. Ora possiamo usare l' espansione dei comandi non quotata per dividere l'output del comando negli argomenti.
$ IFS='#' # split on '#' signs
$ set -f # disable globbing
$ args=( $( ./gen_args3.sh ) ) # assign the values to the array
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
Dovrai tornare IFS
indietro in seguito se dipendi dalla suddivisione delle parole altrove nello script ( unset IFS
dovrebbe funzionare per renderlo predefinito) e utilizzare anche set +f
se vuoi usare il globbing in seguito.
Se non stai usando Bash o qualche altra shell che ha array, puoi usare i parametri posizionali per quello. Sostituisci args=( $(...) )
con set -- $(./gen_args.sh)
e usa "$@"
invece di "${args[@]}"
allora. (Anche qui hai bisogno di virgolette "$@"
, altrimenti i parametri posizionali sono soggetti a divisione di parole.)
eval
potrebbe essere usato, ma generalmente non è raccomandato.xargs
è qualcosa da considerare anche