Isso porque o shell avaliou ; , então eval não o viu.
Você tem que escapar de qualquer caractere especial de shell para atrasar sua avaliação e passar é literalmente para eval :
eval for i in \{"$1".."$2"\}\; do echo \"\$i\"\; done
Estou escrevendo um script que aceita dois argumentos:
#! /bin/bash
eval for i in {$1..$2}; do echo $i; done
Eu corro como:
$ ./myscript 0002 0010
syntax error near unexpected token 'do'
Por que o erro está errado?
Eu acho que pode ser porque o loop deve ser agrupado. Mas substituindo eval for i in {$1..$2}; do echo $i; done por eval { for i in {$1..$2}; do echo $i; done; } , o erro permanece.
Nota:
Espero realizar a expansão de parâmetros antes da expansão de chaves usando eval .
A saída desejada do meu exemplo é 0002 0003 0004 0005 0006 0007 0008 0009 0010 . (Veja Realizar a expansão dos parâmetros antes da expansão da chave? )
Essa linha quebra no primeiro metacaractere, que é ; (neste exemplo).
A linha:
eval for i in {$1..$2}; do echo $i; done
Está dividido nos três comandos:
eval for i in {$1..$2};
do echo $i;
done
A tentativa de executar do sem ter um for , while , until anterior não funciona. Levará uma condição de erro:
syntax error near unexpected token 'do'
Isso acontece porque o for anterior está oculto como um argumento no comando eval .
Uma solução possível é citar tudo e deixar de fora apenas o que você deseja expandir, o que acredito que você queira as variáveis $1 e $2 :
eval 'for i in {'$1'..'$2'}; do echo $i; done'
Funciona:
$ ./myscript 0002 0010
0002
0003
0004
0005
0006
0007
0008
0009
0010
No entanto, esse script é eval uando entrada externa, uma prática altamente insegura.
Um script mais seguro que limpe $ 1 e $ 2 e cite corretamente as variáveis, é este:
#!/bin/bash
a=${1//[^0-9]/} ### select only numbers from first parameter.
b=${2//[^0-9]/} ### select only numbers from second parameter.
eval 'for i in {'"$a"'..'"$b"'}; do echo $i; done'