Operador binário esperado - questão de citação para argumentos de script de shell

1

Eu tenho uma pergunta sobre como estou adicionando argumentos ao executar um script de shell.

Eu tenho um script simples que me ajuda a bloquear os intervalos de ip:

~ / block_ip.sh:

if [ ! $3 ]
then
 echo "usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'"
 exit 1
fi

echo "adding $3"
sudo iptables -I INPUT -s $2 -j $1 -m comment --comment "$3"

Se eu executar isso sem argumentos, a saída é a esperada:

~$ ./block_ip.sh
usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'

No entanto, os espaços parecem ser a causa da saída inesperada de "operador binário esperado" :

~$ ./block_ip.sh DROP '1.0.0.0/8' 'south brisbane qld'
./block_ip.sh: line 1: [: brisbane: binary operator expected
adding south brisbane au

Mas, em seguida, é adicionado apesar da saída inesperada:

Chain INPUT (policy ACCEPT)
num  target     prot opt source           destination
1    DROP       all  --  1.0.0.0/8        anywhere         /* south brisbane au */

Se este é um problema de citação, como faço para formar os argumentos (sem usar barras invertidas para escapar dos espaços)? É claro que espero que eu precise de uma mudança no script, que é uma solução aceitável também.

    
por WEBjuju 08.02.2018 / 16:47

1 resposta

5

Sim, isso é um problema de cotação: [ ! $3 ] expande para [ ! south brisbane qld ] (quatro argumentos entre [ e ] ). E quando ele vê quatro argumentos, com o primeiro um ! , [ espera ver algo como [ ! arg1 op arg2 ] onde op é um operador binário. (isso, novamente, é uma das coisas diferentes entre [ .. ] e [[ .. ]] ; veja este Q e também este Q )

brisbane não é um operador válido, portanto, ele reclama e retorna 2, o que é falso, portanto, as instruções dentro do if não são executadas. Para saber a diferença entre um erro e um teste de falha regular, você precisa testar explicitamente o valor de retorno em relação a 2.

Por outro lado, se $3 estiver vazio, o teste se tornará [ ! ] , um teste de um argumento que verifica se o único argumento não é vazio (é, é a cadeia de um caractere ! ) . Nesse caso, ele funciona como planejado, embora talvez não pelo motivo esperado.

Você deseja que [ ! "$3" ] ou [ -z "$3" ] mantenha a string como um argumento para [ .

É claro que você também pode inverter o sentido do teste e fazer o trabalho real dentro do if , para que um erro no teste evite a execução dos comandos principais. Mas isso tornaria a estrutura do código um pouco mais clara.

    
por 08.02.2018 / 16:54