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'