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 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 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, 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 formo os argumentos (sem usar barras invertidas para escapar dos espaços)? Claro, espero precisar de uma mudança no script, que também é uma solução aceitável.
Sim, isso é um problema de citação:
[ ! $3 ]
expande para[ ! south brisbane qld ]
(quatro argumentos entre[
e]
). E quando ele vê quatro argumentos, sendo o primeiro a!
,[
espera ver algo como[ ! arg1 op arg2 ]
whereop
is a binary operator. (isso, novamente, é uma das coisas diferentes entre[ .. ]
e[[ .. ]]
; veja este Q e também este Q )brisbane
não é um operador válido, então ele reclama e retorna 2, que é falso, então as instruções dentro deif
não são executadas. Para saber a diferença entre um erro e um teste com 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 torna[ ! ]
, um teste de um argumento que verifica se o único argumento não está vazio (é, é a string de um caractere!
). Nesse caso, funciona como pretendido, embora talvez não pelo motivo que você esperaria.Você deseja
[ ! "$3" ]
ou[ -z "$3" ]
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
, para que um erro no teste evite a execução dos comandos principais. Mas isso tornaria a estrutura do código um pouco mais confusa.