bash中if语句的嵌套条件

时间:2018-07-04 13:42:43

标签: bash shell if-statement

我想检查两个变量中的两个都没有设置。我尝试了多种选择,这是我想到的最干净的解决方案:

if [ ! -z $A -a -z $B ] || [ -z $A -a ! -z $B ]; then
  #error
fi
  #success

当我同时设置A和B来运行脚本时,它运行良好。但是当我在缺少A的情况下运行它时,会得到:

./test.sh: line 3: [: too many arguments
./test.sh: line 3: [: too many arguments

第3行是条件语句。

当我在缺少B的情况下运行它时,我得到:

./test.sh: line 3: [: argument expected
./test.sh: line 3: [: argument expected

是因为我的条件语法错误还是我想念其他东西?

3 个答案:

答案 0 :(得分:3)

引用变量:

if [ ! -z "$A" -a -z "$B" ] || [ -z "$A" -a ! -z "$B" ]; then

如果变量未加引号且未设置,则它们将被替换为空,这意味着该命令实际上变为:

if [ ! -z -a -z ] || [ -z -a ! -z ]; then

导致您看到的错误。

答案 1 :(得分:3)

您应尽量避免使用-a;它是非标准的,并且被POSIX标准视为过时的。由于||&&的优先级相同,因此您需要使用{ ... }对各个测试进行正确分组。

(这是除了立即需要引用参数扩展之外的内容。)

if { [ ! -z "$A" ] && [ -z "$B" ]; } || { [ -z "$A" ] && [ ! -z "$B" ]; }; then

但是,更简单的表达式可能是

if [ -z "$A$B" ] || { [ "$A" ] && [ "$B" ]; }; then
  1. 当且仅当两个字符串也为空时,两个字符串的串联才为空。
  2. [ "$A" ][ -n "$A" ]的缩写,等效于[ ! -z "$A" ]

使用bash的{​​{1}}命令,您可以编写更自然的

[[ ... ]]

在这种情况下,报价是可选的,并且if [[ -z $A && -n $B || -n $A && -z $B ]]; ||可以在&&内部使用,并且具有您期望的优先级。

答案 2 :(得分:1)

您忘了在变量周围使用引号:

if [ ! -z "$A" -a -z "$B" ] || [ -z "$A" -a ! -z "$B" ]; then
    echo "error"
fi

Bash将用值替换脚本中的var,因此当未设置A=5B时,您的版本将显示为:

if [ ! -z 5 -a -z  ] || [ -z 5 -a ! -z ]; then

您看到语法错误,因为-z需要一个参数。使用引号时,显示为:

if [ ! -z "5" -a -z "" ] || [ -z "5" -a ! -z "" ]; then

如您所见,B的参数现在是一个空字符串,有效。

如果将A="string with spaces"设置为无引号,则您的版本也会失败。