Eu escrevi um script que pode gerar esses argumentos para mim, com aspas
Se a saída for citada corretamente para o shell e você confiar na saída , poderá executá eval
-lo.
Supondo que você tenha um shell que suporte matrizes, seria melhor usar um para armazenar os argumentos obtidos.
Se ./gen_args.sh
produzir saída como 'foo bar' '*' asdf
, então poderíamos executar eval "args=( $(./gen_args.sh) )"
para preencher uma matriz chamada args
com os resultados. Isso seria os três elementos foo bar
, *
, asdf
.
Podemos usar "${args[@]}"
como de costume para expandir os elementos da matriz individualmente:
$ eval "args=( $(./gen_args.sh) )"
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
(Observe que as aspas. Se "${array[@]}"
expandem para todos os elementos como argumentos distintos, sem modificação. Sem aspas, os elementos da matriz estão sujeitos à divisão de palavras. Veja, por exemplo, a página Matrizes no BashGuide .)
No entanto , eval
é possível executar com êxito quaisquer substituições de shell, portanto $HOME
, a saída seria expandida para o diretório inicial e uma substituição de comando realmente executaria um comando no shell em execução eval
. Uma saída de "$(date >&2)"
criaria um único elemento vazio da matriz e imprimiria a data atual no stdout. Isso é preocupante se gen_args.sh
obtém os dados de alguma fonte não confiável, como outro host na rede, nomes de arquivos criados por outros usuários. A saída pode incluir comandos arbitrários. (Se get_args.sh
ele era malicioso, não precisaria produzir nada, apenas poderia executar os comandos maliciosos diretamente.)
Uma alternativa à citação de shell, que é difícil de analisar sem avaliação, seria usar algum outro caractere como separador na saída do seu script. Você precisaria escolher um que não seja necessário nos argumentos reais.
Vamos escolher #
e ter a saída do script foo bar#*#asdf
. Agora, podemos usar a expansão de comando sem aspas para dividir a saída do comando nos 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:
Você precisará IFS
voltar mais tarde se depender da divisão de palavras em algum lugar do script ( unset IFS
deve funcionar para torná-lo o padrão) e também usar set +f
se quiser usar globbing mais tarde.
Se você não estiver usando o Bash ou algum outro shell que possua matrizes, use os parâmetros posicionais para isso. Substitua args=( $(...) )
por set -- $(./gen_args.sh)
e use em "$@"
vez "${args[@]}"
disso. (Também aqui você precisa de aspas "$@"
, caso contrário, os parâmetros posicionais estão sujeitos à divisão de palavras.)
eval
possa ser usado, mas geralmente não é recomendado.xargs
é algo a considerar também