Eu tenho uma variável bash
shell contendo uma string formada por várias palavras delimitadas por espaço em branco. A cadeia pode conter fugas, como espaço em branco em escape dentro de uma palavra. Palavras contendo espaço em branco podem ser citadas alternativamente.
Uma variável de shell usada sem aspas ( $FOO
em vez de "$FOO"
) se torna várias palavras, mas aspas e escapes na string original não têm efeito.
Como uma string pode ser dividida em palavras, considerando caracteres citados e escapados?
Antecedentes
Um servidor oferece acesso restrito a ssh
usando a opção ForceCommand
no arquivo sshd_config
para forçar a execução de um script, independentemente da linha de comando dada ao cliente ssh
.
O script usa a variável SSH_ORIGINAL_COMMAND
(que é uma sequência, definida por ssh
, que contém a linha de comandos fornecida ao cliente ssh
) para definir sua lista de argumentos antes de continuar. Então, um usuário fazendo
$ ssh some_server foo 'bar car' baz
verá o script ser executado e terá SSH_ORIGINAL_COMMAND
definido como foo bar car baz
, o que se tornaria quatro argumentos quando o script for
set -- ${SSH_ORIGINAL_COMMAND}
Não é o resultado desejado. Então o usuário tenta novamente:
$ ssh some_server foo bar\ car baz
O mesmo resultado - a barra invertida no segundo argumento precisa ser escapada para o shell do cliente, então ssh
o vê. E sobre estes:
$ ssh some_server foo 'bar\ car' baz
$ ssh some_server foo bar\ car baz
Ambos funcionam, assim como o printf "%q"
quoting wrapper , que pode simplificar a citação do lado do cliente.
A cotação do lado do cliente permite que ssh
envie a string corretamente citada para o servidor, de forma que ela receba SSH_ORIGINAL_COMMAND
com a barra invertida intacta: foo bar\ car baz
.
No entanto, ainda existe um problema porque set
não considera a citação ou o escape. Existe uma solução:
eval set -- ${SSH_ORIGINAL_COMMAND}
mas é inaceitável. Considere
$ ssh some_server \; /bin/sh -i
Muito indesejável: eval
não pode ser usado porque a entrada não pode ser controlada.
O que é necessário é o recurso de expansão de string de eval
sem a parte de execução.