Uma situação com a qual me deparei algumas vezes: tenho uma função de shell que faz algumas configurações e depois invoca um comando mais ou menos arbitrário, como este:
setup_and_run() {
some_setup_commands
"$@"
}
Eu quero alterar esta função para também escrever um arquivo de script que eu possa usar para executar novamente o comando depois de fazer a mesma configuração. Posso fazer o seguinte, que funciona quando não há argumentos com espaços ou outras coisas estranhas no comando:
setup_and_run() {
some_setup_commands
cat >>rerun.sh <<EOF
some_setup_commands
$@
EOF
"$@"
}
Existe uma maneira padrão de alterar isso para que o script seja escrito com aspas adequadas, em geral, mesmo que alguns argumentos tenham espaços ou outros caracteres especiais?
Por exemplo, com a segunda definição de setup_and_run
, se eu executar
$ setup_and_run ls "my cat's \"password\""
my cat's "password"
então rerun.sh
conterá
some_setup_commands
ls my cat's "password"
Considerando que eu quero que contenha algo como
some_setup_commands
ls "my cat's \"password\""
ou
some_setup_commands
ls my\ cat\'s\ \"password\"
ou algo assim.
Em um piscar de olhos, posso terceirizar isso para algo como Python's shlex.quote()
, mas estou procurando algo que possa ser feito no próprio shell, se possível, ou pelo menos usando uma ferramenta UNIX padrão mais leve.
No bash, ksh93 e zsh, você pode usar o
%q
escape para oprintf
arquivo .No bash, você pode usar o
printf -v
para gravar a saída em uma variável em vez de na saída padrão.No zsh, há um método diferente que é o
q
sinalizador de expansão de parâmetro , seguido porj: :
para unir os elementos da matriz com um espaço.Em sh simples, é mais difícil. Uma maneira confiável de citar uma palavra é colocá-la entre aspas simples e substituir cada aspa dentro dela por
'\''
. Fazer a substituição corretamente não é muito fácil, envolvendo uma chamada externa para sed ou um loop.