Escribí un script que puede generar esos argumentos para mí, con citas
Si la salida se cita correctamente para el shell y confía en la salida , entonces podría ejecutarla eval
.
Suponiendo que tiene un shell que admite matrices, sería mejor usar uno para almacenar los argumentos que obtiene.
Si ./gen_args.sh
produce resultados como 'foo bar' '*' asdf
, entonces podríamos ejecutar eval "args=( $(./gen_args.sh) )"
para completar una matriz llamada args
con los resultados. Eso sería los tres elementos foo bar
, *
, asdf
.
Podemos usar "${args[@]}"
como de costumbre para expandir los elementos de la matriz individualmente:
$ eval "args=( $(./gen_args.sh) )"
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
(Tenga en cuenta las comillas. Se "${array[@]}"
expande a todos los elementos como argumentos distintos sin modificar. Sin comillas, los elementos de la matriz están sujetos a la división de palabras. Consulte, por ejemplo, la página Arrays en BashGuide ).
Sin embargo , eval
ejecutará $HOME
con gusto cualquier sustitución de shell, por lo que en la salida se expandiría a su directorio de inicio, y una sustitución de comando realmente ejecutaría un comando en la ejecución de shell eval
. Una salida de "$(date >&2)"
crearía un único elemento de matriz vacío e imprimiría la fecha actual en stdout. Esto es preocupante si gen_args.sh
obtiene los datos de alguna fuente no confiable, como otro host en la red, nombres de archivos creados por otros usuarios. La salida podría incluir comandos arbitrarios. (Si en get_args.sh
sí mismo fuera malicioso, no necesitaría generar nada, simplemente podría ejecutar los comandos maliciosos directamente).
Una alternativa a la cita de shell, que es difícil de analizar sin eval, sería usar algún otro carácter como separador en la salida de su script. Debería elegir uno que no sea necesario en los argumentos reales.
Vamos a elegir #
y tener la salida del script foo bar#*#asdf
. Ahora podemos usar la expansión de comandos sin comillas para dividir la salida del comando en los argumentos.
$ 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:
Tendrá que volver a configurarlo IFS
más tarde si depende de la división de palabras en otra parte del script ( unset IFS
debería funcionar para que sea el predeterminado), y también usarlo set +f
si desea usar globbing más adelante.
Si no está utilizando Bash o algún otro shell que tenga matrices, puede usar los parámetros posicionales para eso. Reemplace args=( $(...) )
con set -- $(./gen_args.sh)
y use en "$@"
lugar de "${args[@]}"
entonces. (Aquí, también, necesita comillas "$@"
, de lo contrario los parámetros posicionales están sujetos a la división de palabras).
eval
podría usarse, pero generalmente no se recomienda.xargs
es algo a considerar también