Erro quando eval for for-loop

0

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? )

    
por Tim 23.04.2016 / 03:33

2 respostas

6

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
    
por 23.04.2016 / 03:45
1

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.

Solução Correta

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'
    
por 23.04.2016 / 07:08

Tags