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
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!
$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 ]
.