Como posso executar uma variável bash como um comando exatamente sem cotação adicional? [duplicado]

6

Estou tentando criar um script que precise salvar um comando para ser executado como uma string. A cadeia em questão precisa conter aspas e, ao tentar executá-la, o bash adiciona caracteres de cotação adicionais, o que, em alguns casos, faz com que o comando não seja executado como esperado.

Aqui está um script de exemplo. O comando example executado neste script de exemplo obviamente não faz nada e ele simplesmente diz command not found , mas você ainda pode executar o script e ver do que estou falando porque adicionei -x ao #!/bin/bash line para que o comando exato sendo executado seja impresso.

Exemplo:

#!/bin/bash -x

#command typed explicitly
example -options "-i filename"

#command stored in string first
commandstring='example -options "-i filename"'
echo "running command: ${commandstring}"
${commandstring}

A saída da execução deste script para mim é (ignorando os dois erros "comando não encontrado"):

+ example -options '-i filename'
+ commandstring='example -options "-i filename"'
+ echo 'running command: example -options "-i filename"'
running command: example -options "-i filename"
+ example -options '"-i' 'filename"'

Assim, você pode ver que a primeira linha do curso é executada como esperado, fornecendo o parâmetro da linha de comando:

-i filename

No entanto, embora o comando echo imprima a seqüência de caracteres de uma maneira que também seria executada perfeitamente, quando a cadeia é colocada na linha de comando ela muda e o parâmetro sendo transmitido se torna

'"- i' 'nome do arquivo"'

, que contém caracteres de aspas adicionais, e isso está fazendo com que o comando real que estou usando no meu script real falhe.

Existe alguma maneira de evitar isso?

    
por stss 10.10.2014 / 03:41

1 resposta

13

Se você estiver usando bash , a maneira mais fácil de salvar um comando exatamente é colocá-lo em uma matriz. Se o comando que você deseja executar for:

example -options "-i filename"

você pode salvá-lo em uma variável de matriz com:

commandline=(example -options "-i filename")

Em seguida, você pode executar o comando salvo exatamente como está @, expondo a matriz entre aspas duplas:

"${commandline[@]}"

A principal coisa a saber aqui é que o shell trata caracteres de aspas ( "'\ ) de maneira diferente quando digitado diretamente na linha de comando a partir de quando os encontra dentro de uma expansão variável como em seu ${commandstring} . Na linha de comando, os caracteres de citação têm uma função de citação especial. Dentro de uma expansão de parâmetro, eles são apenas caracteres normais não especiais. Portanto, "-i filename" é uma única palavra quando digitado na linha de comando que é analisada como -i filename , mas os mesmos caracteres em uma variável expandem para as palavras "-i e filename" .

BashFAQ 50 aborda este tópico com muito mais detalhes.

    
por 10.10.2014 / 04:02

Tags