Resposta curta: veja BashAQ # 50: Estou tentando colocar um comando em uma variável, mas os casos complexos sempre falham! .
Resposta longa: é por causa da ordem em que o bash analisa a linha de comando. Especificamente, ele procura por coisas como pipes e redirecionamentos antes de expandir os valores das variáveis, e não volta e procura por canos, etc. nos valores expandidos. Essencialmente, as variáveis são substituídas na metade do processo de análise, de modo que o valor só é analisado pela metade antes de ser executado.
Para resolver isso, você precisa responder a pergunta do @shhck: por que o comando é armazenado em uma variável em primeiro lugar? Qual é o problema real que você está tentando resolver? Dependendo do objetivo real, há várias soluções possíveis:
-
Não armazene em uma variável, apenas execute diretamente. Armazenar comandos para uso posterior é complicado, e se você realmente não precisa, simplesmente não faça isso.
-
Use uma função em vez de uma variável. É para isso que eles servem, afinal de contas:
i() { cat -nT index.php |grep 'someregex'; } i
A principal desvantagem disso é que você não pode criar a função dinamicamente - você não pode incluir ou excluir condicionalmente o código da função (embora a própria função possa ter elementos condicionais selecionados quando ela é executada).
-
Use
eval
. Isso deve ser considerado um último recurso, já que é fácil obter um comportamento inesperado. Ele essencialmente executa o comando por meio de outro passo de análise completo, de modo que todos os pipes etc. obtêm seu significado completo - mas também significa que partes do comando que você considerava apenas dados também serão analisadas e talvez executadas. Nomes de arquivos que contêm metacaracteres de shell (pipe, ponto e vírgula, citação / apóstrofo, etc) podem ter efeitos estranhos e às vezes perigosos. Se você usareval
, ao menos a aspas duplas, caso contrário, seu conteúdo será analisado uma vez e meia, com resultados ainda mais estranhos.i="cat -nT index.php |grep 'someregex'" eval "$i"
EDIT: Outra abordagem padrão de armazenar um comando em uma variável é usar uma matriz em vez de uma variável simples. Isso permite armazenar um comando com argumentos complexos (por exemplo, contendo espaços) sem problemas, mas não armazena coisas como pipes e redirecionamentos. Portanto, a abordagem da matriz não será útil nesse caso específico.