bash 中 if 语句的嵌套条件

Mil*_*iez 5 bash shell if-statement

我想检查两个变量是否都已设置或均未设置。我尝试了多种选择,这是我想出的最干净的解决方案:

if [ ! -z $A -a -z $B ] || [ -z $A -a ! -z $B ]; then
  #error
fi
  #success
Run Code Online (Sandbox Code Playgroud)

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

./test.sh: line 3: [: too many arguments
./test.sh: line 3: [: too many arguments
Run Code Online (Sandbox Code Playgroud)

第 3 行是条件语句。

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

./test.sh: line 3: [: argument expected
./test.sh: line 3: [: argument expected
Run Code Online (Sandbox Code Playgroud)

是我的情况语法错误还是我错过了其他东西?

che*_*ner 8

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

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

if { [ ! -z "$A" ] && [ -z "$B" ]; } || { [ -z "$A" ] && [ ! -z "$B" ]; }; then
Run Code Online (Sandbox Code Playgroud)

然而,更简单的表达可能是

if [ -z "$A$B" ] || { [ "$A" ] && [ "$B" ]; }; then
Run Code Online (Sandbox Code Playgroud)
  1. 当且仅当两个字符串也为空时,两个字符串的串联才是空的。
  2. [ "$A" ]是 的缩写[ -n "$A" ],相当于[ ! -z "$A" ].

使用bash's[[ ... ]]命令,可以写得更自然

if [[ -z $A && -n $B || -n $A && -z $B ]];
Run Code Online (Sandbox Code Playgroud)

在这种情况下,引号是可选的,并且||可以按照您期望的优先级&&在内部使用。[[ ... ]]


use*_*001 3

引用你的变量:

if [ ! -z "$A" -a -z "$B" ] || [ -z "$A" -a ! -z "$B" ]; then
Run Code Online (Sandbox Code Playgroud)

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

if [ ! -z -a -z ] || [ -z -a ! -z ]; then
Run Code Online (Sandbox Code Playgroud)

导致您看到的错误。

  • 现在就杀了我……就这么简单吗?!谢谢,它有效。 (3认同)