预期的二元运算符 - 引用 shell 脚本参数的问题

WEB*_*uju 2 bash shell-script whitespace arguments

我有一个关于在执行 shell 脚本时如何添加参数的问题。

我有一个简单的脚本可以帮助我阻止 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"
Run Code Online (Sandbox Code Playgroud)

如果我在没有参数的情况下执行此操作,则输出符合预期:

~$ ./block_ip.sh
usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'
Run Code Online (Sandbox Code Playgroud)

然而,空格似乎是“二元运算符预期”意外输出的原因:

~$ ./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
Run Code Online (Sandbox Code Playgroud)

但是尽管有意外的输出,它还是添加了它:

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

如果这是一个引用问题,我该如何形成参数(不使用反斜杠来转义空格)?当然,我希望我可能需要更改脚本,这也是一个可以接受的解决方案。

ilk*_*chu 8

是的,这是一个引用问题:[ ! $3 ]扩展为[ ! south brisbane qld ][和之间的四个参数])。当它看到四个参数时,第一个 a ![期望看到类似[ ! arg1 op arg2 ]where opis 一个二元运算符的东西。(这又是[ .. ]和之间的不同之处之一[[ .. ]]参见这个 Q这个 Q

brisbane不是有效的运算符,因此它会抱怨并返回 2,这是错误的,因此if不会执行其中的语句。要区分错误和常规失败测试,​​您需要针对 2 显式测试返回值。

另一方面,如果$3为空,则测试变为[ ! ],一个单参数测试,用于检查唯一参数是否为非空(它是单字符串!)。在这种情况下,它会按预期工作,尽管可能不是您期望的原因。


您希望[ ! "$3" ][ -z "$3" ]将字符串保留为 的一个参数[

当然你也可以颠倒测试的意义,在里面做实际的工作if,这样测试中的错误就可以避免运行主命令。但这会使代码结构更加不清楚。