Executando um comando construído a partir do script bash

3

Eu construí um comando como este em um script bash

a="my_cmd";
a="$a --verbose";
echo $a;
$a;

Funciona e executa meu comando corretamente. Mas quando eu adiciono uma variável de ambiente ao mix, ela quebra.

a="my_cmd";
a="URL=myurl $a --verbose";
echo $a;
$a;

Ele quebra em "URL = myurl" dizendo Não há tal arquivo ou diretório, mas se eu o executar usando eval (), o comando funciona corretamente.

a="my_cmd";
a="URL=myurl $a --verbose";
echo $a;
eval "$a";

Alguém pode gentilmente explicar por que adicionar a variável de ambiente à mistura quebrou meu comando no segundo exemplo.

    
por Jithin 03.03.2015 / 00:58

1 resposta

4

Quando você deixa uma expansão variável sem aspas, ela passa por divisão de palavras e expansão de nome de arquivo (ou seja, globbing). Não é analisado como um comando shell. Em geral, quando você constrói dinamicamente um fragmento de shell para executar, o caminho certo para executá-lo é eval "$a" , em que a contém a string para analisar como código de shell.

Em seu primeiro snippet, o valor de a é a string my_cmd --verbose . A divisão de palavras divide-a em duas palavras my_cmd e --verbose . Globbing não faz nada, pois não há curingas em nenhuma das palavras. O comando resultante da expansão de $a consiste em duas palavras my_cmd e --verbose , então o comando my_cmd (que pode ser um alias, uma função, um builtin ou um executável no PATH) é executado com o único argumento --verbose .

No segundo snippet, as coisas são semelhantes, com três palavras resultantes da expansão: URL=myurl , my_cmd e --verbose . Isso resulta em uma tentativa de executar o comando URL=myurl com dois argumentos.

O comando shell URL=myurl my_cmd --verbose é analisado de forma diferente: a primeira palavra é analisada como uma atribuição à variável URL e, como há um nome de comando após ela, a atribuição define a variável de ambiente apenas pela duração do comando. . Isso faz parte da análise, não de algo que é feito após a expansão, portanto, para que o sinal de igual faça parte do código-fonte do shell, o sinal de igual não pode ser o resultado de alguma expansão.

Não armazene um comando com parâmetros em uma string . Use uma matriz. Para um comando complexo, como aquele em que você define variáveis ou executa o redirecionamento, além de executar o comando, use uma função, se possível, e, se não, use eval (tomando muito cuidado com as citações adequadas).

    
por 03.03.2015 / 01:27