Você precisa citar "$cmd"
- e talvez evite as aspas duplas "
. De qualquer forma, para executar isso você precisa eval
- e isso é devido ao |pipe
. Uma variável de shell não se expande além dos limites de um único comando simples - e você está tentando executar um comando composto.
Então:
cmd='grep -i "word1" filename | grep -i "word2"'
eval "$cmd"
Provavelmente, quando você estava expandindo $cmd
sem aspas, correu para geração de nome de arquivo e / ou $IFS
problemas. Apenas certifique-se de que é citado de forma confiável e você ficará bem. Também verifique se o que está em "word[12]"
não contém aspas duplas ou barras invertidas ou qualquer outra coisa - senão você precisará reavaliar seu estilo de citação lá.
Olhando mais de perto para o seu erro e posso dizer exatamente o que foi:
grep: |: No such file or directory
grep: grep: No such file or directory
Então, se eu fizer isso:
echo | echo
A primeira echo
imprime uma \n
ewline para a segunda echo
' stdin
. Se eu fizer:
set \| echo
echo "$@"
O primeiro echo
imprime cada um dos seus argumentos, que são |
pipe e echo
, respectivamente.
A diferença é que o |
pipe no primeiro caso é interpretado pelo analisador do shell como um token e é interpretado como tal. No segundo caso, ao mesmo tempo em que o shell está verificando o token de |
do canal, ele também está verificando o token $
expand - e assim o |
pipe ainda não está lá porque "$@"
tem ainda não foi substituído pelo seu valor.
Então, se você fizer isso:
grep -i "word" filename \| grep -i "word2"
... é provável que você obtenha os mesmos resultados porque o |
não delimita os comandos e, em vez disso, é um argumento para grep
em sua posição infiles .
Veja aqui quantos campos você recebe quando divide $cmd
com o valor padrão $IFS
:
printf '<%s> ' $cmd
<grep> <-i> <"word1"> <filename> <|> <grep> <-i> <"word2">
E aqui está o que a geração de nome de arquivo pode fazer:
touch 'echo 1simple &&' 'echo 2simple'
eval echo*