Operador binário esperado – pergunta de citação para args de script de shell

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

Eu tenho um script simples que me ajuda a bloquear 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 será 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 do 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 então ele adiciona 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 for um problema de citação, como faço para formar os argumentos (sem usar barras invertidas para escapar dos espaços)? Claro, espero que precise de uma mudança para o script, essa também é uma solução aceitável.

Comentários

  • Se seu objetivo no teste $3 é apenas para ter certeza de que existem três parâmetros, então você pode usar a variável de shell $# mais simples, que contém o número de parâmetros, por exemplo. if [ $# -ne 3 ].

Resposta

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

brisbane não é um operador válido, então reclama e retorna 2, que é falso, então as declarações dentro do if não são executados. Para saber a diferença entre um erro e um teste de falha regular, você “precisaria 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 está vazio (é, é a string de um caractere !). Nesse caso, funciona como esperado, embora talvez não pelo motivo que você “esperaria.


Você deseja [ ! "$3" ] ou [ -z "$3" ] para manter 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, de modo que um erro no teste evitasse a execução dos comandos principais. Mas isso tornaria a estrutura do código um pouco mais confusa.

Comentários

  • bom – então o motivo pelo qual está funcionando é que, embora haja erros, $ 3 não está ' vazio, portanto passa no! teste e cito no comando iptables para que sua expansão para incluir espaços já tenha sido tratada – certo?
  • e eles ' Também desejarei citar os parâmetros na linha iptables
  • @WEBjuju, ah sim, pretendia escrever sobre isso, editei por que funciona. E sim,você tinha as aspas no comando iptables, então funciona bem.
  • @ilkkachu gotcha, sim, parece bobo da minha parte. de alguma forma, eu sabia disso subconscientemente, mas não conseguia ' t trazer o conhecimento para uma solução funcional. De alguma forma, consegui progredir sem conhecer esse inquilino básico até agora, mas simplesmente subi de nível. muito obrigado!

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *