Resposta curta: consulte 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 coisas como pipes e redirecionamentos antes de expandir valores variáveis, e não volta e procura novamente pipes etc. nos valores expandidos. Essencialmente, as variáveis são substituídas na metade do processo de análise, portanto, o valor é analisado apenas na metade antes de ser executado.
Para resolver isso, você precisa responder à pergunta de @ slhck: 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, existem várias soluções possíveis:
Não o armazene em uma variável, apenas execute-o diretamente. O armazenamento de comandos para uso posterior é complicado e, se você realmente não precisa, simplesmente não precisa.
Use uma função em vez de uma variável. Afinal, é para isso que eles servem:
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 que são selecionados quando são executados).
Use eval
. Isso deve ser considerado um último recurso, pois é fácil obter um comportamento inesperado. Essencialmente, ele executa o comando através de outra passagem de análise completa, para que todos os pipes etc. tenham todo o significado - mas também significa que partes do comando que você pensou serem apenas dados também serão analisadas e talvez executadas. Os nomes de arquivos que contêm metacaracteres de shell (tubo, ponto-e-vírgula, aspas / apóstrofo, etc.) podem ter efeitos estranhos e às vezes perigosos. Se você usar eval
, pelo menos aspas duplas na string, caso contrário, seu conteúdo será essencialmente analisado uma vez e meia, com resultados ainda mais estranhos.
i="cat -nT index.php |grep 'someregex'"
eval "$i"
Edição: Outra abordagem padrão de armazenar um comando em uma variável é usar uma matriz em vez de uma variável simples. Isso permite que você armazene um comando com argumentos complexos (por exemplo, contendo espaços) sem problemas, mas não armazena itens como pipes e redirecionamentos. Portanto, a abordagem de matriz não será útil nesse caso específico.