Bash 中的 If else 条件

hym*_*ode 4 bash shell-script

我正在尝试创建一个if else使用 3 个布尔变量的 bash 脚本:

  1. CHECK_X
  2. CHECK_Y
  3. CHECK_Z

如果CHECK_XorCHECK_Y为假并且CHECK_Z也是假,那么我通知用户条件不满足。所以我创建了以下内容:

if [[ "$CHECKX" || "$CHECKY" == "FALSE" ]] && [[ "$CHECKZ" == "FALSE" ]]; then
  echo "Condition not met"
fi
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,如果 或CHECK_X是CHECK_Y正确的,尽管CHECK_Z仍然为假,则条件继续,这不是我想要的。

在满足我的条件之前,我需要CHECK_X和CHECK_Z为真,或者CHECK_Y且CHECK_Z为真。

使用以下代码也不起作用:

if [[ "$CHECK_X" && "$CHECK_Z" == "FALSE" ]] || [[ "$CHECK_Y" && "$DCHECK_Z" == "FALSE" ]]; then
  echo "Condition not met"
fi    
Run Code Online (Sandbox Code Playgroud)

我认为我在某个地方把自己搞得太复杂了,希望得到一些专家的建议。谢谢

更新:

根据最近的一些反馈,我将代码更新为:

if [[ "$CHECK_X" == "FALSE" || "$CHECK_Y" == "FALSE" ]] && [[ "$CHECK_Z" == "FALSE" ]]; then
  echo "Condition not met"
fi
Run Code Online (Sandbox Code Playgroud)

然而经过测试我有以下...

如果:

  1. CHECK_X="TRUE"
  2. CHECK_Y="FALSE"
  3. CHECK_Z="TRUE"

输出:Condition not met。这是不正确的,因为条件1和3是TRUE。

如果:

  1. CHECK_X="TRUE"
  2. CHECK_Y="FALSE"
  3. CHECK_Z="FALSE"

输出:Condition not met。这是正确的,因为条件1和3都不成立 TRUE。

如果:

  1. CHECK_X="FALSE"
  2. CHECK_Y="TRUE"
  3. CHECK_Z="FALSE"

输出:脚本完成。这是不正确的,因为条件2和3不成立 TRUE。

如果:

  1. CHECK_X="FALSE"
  2. CHECK_Y="TRUE"
  3. CHECK_Z="TRUE"

输出:脚本完成。这是正确的,因为条件2和3是TRUE。

如果:

  1. CHECK_X="FALSE"
  2. CHECK_Y="FALSE"
  3. CHECK_Z="FALSE"

输出:Condition not met。这是正确的,因为条件1和3或2和3不成立 TRUE。

ter*_*don 8

您需要检查每个变量:

if [[ "$CHECKX" == "FALSE" || "$CHECKY" == "FALSE" ]] && [[ "$CHECKZ" == "FALSE" ]]; then
  echo "Condition not met"
fi
Run Code Online (Sandbox Code Playgroud)

当你有 时if [[ "$CHECKX" || "$CHECKY" == "FALSE" ]],这只是检查是否$CHECKX已设置,它仅$CHECKY与字符串进行比较FALSE。为了显示:

$ CHECKX=foo
$ CHECKY=TRUE
$ [[ "$CHECKX" || "$CHECKY" == "FALSE" ]] && echo true
true
$ CHECKX=""
$ [[ "$CHECKX" || "$CHECKY" == "FALSE" ]] && echo true
$ 
Run Code Online (Sandbox Code Playgroud)

正如您在上面看到的,仅当CHECKX设置为空字符串时检查才会失败,因此测试[[ "$CHECKX" ]]评估为 false。如果它设置为任何值,包括0,那么它就会失败:

$ CHECKX=0
$ [[ "$CHECKX" || "$CHECKY" == "FALSE" ]] && echo true
true
Run Code Online (Sandbox Code Playgroud)


Jim*_* L. 7

其他人已经解决了用于存储和测试布尔值和变量的编码技术,因此我将只关注代码的逻辑。

当您正在研究多变量布尔函数时,请构建一个真值表,以便您清楚函数的正确输出应该是什么。请检查我是否正确理解了您的帖子,但我相信对于函数,Q(X,Y,Z)的值Q取决于X,Y如下Z所示:

“如果 X 或 Y 为假且 Z 也为假,那么……条件不满足。”

因为您已经否定了这一点,所以我将假设在所有其他情况下都满足该条件。

X 是 Z 问
错误的 错误的 错误的 错误的
错误的 错误的 真的 真的
错误的 真的 错误的 错误的
错误的 真的 真的 真的
真的 错误的 错误的 错误的
真的 错误的 真的 真的
真的 真的 错误的 真的
真的 真的 真的 真的

布尔代数中的一个常见公理是,我们可以构建两个子函数 Q1 和 Q2 来解决表的互斥部分,而不是构建一个函数 Q 来解决所有情况。然后我们可以对ORQ1和Q2的结果进行简单处理,得到最终的解Q。

例如,令 Q1X为表上半部分中为 FALSE 的解。请注意,在这四种情况下,Z和Q列是相同的。该Y列是无关的,因此我们可以说当为XFALSE 时,函数结果与 直接相关Z:

for X=FALSE, Q1 = !X && Z
Run Code Online (Sandbox Code Playgroud)
X 是 Z Q1
错误的 错误的 错误的 错误的
错误的 错误的 真的 真的
错误的 真的 错误的 错误的
错误的 真的 真的 真的

在表的下半部分,其中X为 TRUE,函数结果 Q2 直接与 相关Y || Z:

for X=TRUE, Q2 = X && (Y || Z)
Run Code Online (Sandbox Code Playgroud)
X 是 Z Q2
真的 错误的 错误的 错误的
真的 错误的 真的 真的
真的 真的 错误的 真的
真的 真的 真的 真的

由于 Q1 和 Q2 是在完全独立的域上定义的,因此我们可以说结果 Q 将恰好是其中之一。那是,

Q = Q1 || Q2
Run Code Online (Sandbox Code Playgroud)
X 是 Z Q1 Q2 Q1 || Q2
错误的 错误的 错误的 错误的 错误的
错误的 错误的 真的 真的 真的
错误的 真的 错误的 错误的 错误的
错误的 真的 真的 真的 真的
真的 错误的 错误的 错误的 错误的
真的 错误的 真的 真的 真的
真的 真的 错误的 真的 真的
真的 真的 真的 真的 真的

现在我们需要将这两种情况组合成一个布尔公式。简单地连接所有内容很诱人,但对于正确的布尔公式,我们必须考虑计算的顺序。与普通代数类似,乘法在加法之前执行,布尔代数规定交集 (AND) 在并集 (OR) 之前执行。因此,我们将在子表达式两边加上括号。

两者皆为X假,我们的结果是Z:

if !X then Q1 = Z
Run Code Online (Sandbox Code Playgroud)

或者X是真的,我们的结果是Y || Z:

if  X then Q2 = Y || Z
Run Code Online (Sandbox Code Playgroud)

我们的答案实际上是一个或另一个:

Q = (!X && Q1) || (X && Q2)
Run Code Online (Sandbox Code Playgroud)

联合的短路评估和换向将使我们能够将其重新表述为:

Q = (X && Q2) || (Q1)
Run Code Online (Sandbox Code Playgroud)

代入 Q1 和 Q2:

Q = (X && (Y || Z)) || (Z)
Run Code Online (Sandbox Code Playgroud)

仅在需要的地方使用括号:

Q = X && (Y || Z) || Z
Run Code Online (Sandbox Code Playgroud)

也可以写成:

Q = Z || X && (Y || Z) 
Run Code Online (Sandbox Code Playgroud)

当 Z 为真时,OR 的右侧无关紧要。当 Z 为假时,OR 的右侧变为:

X && (Y || FALSE)
Run Code Online (Sandbox Code Playgroud)

要不就:

X && Y
Run Code Online (Sandbox Code Playgroud)

所以我们最终的函数 Q 是:

Q = Z || X && Y
Run Code Online (Sandbox Code Playgroud)

我们可以根据真值表来验证这一点,因为在每种情况下,当 Z 为真时,Q 也为真。在 Z 为假的四种情况下,只有当 X 和 Y 都为真时,Q 才为真。

X 是 Z X && Y 问
错误的 错误的 错误的 错误的 错误的
错误的 错误的 真的 错误的 真的
错误的 真的 错误的 错误的 错误的
错误的 真的 真的 错误的 真的
真的 错误的 错误的 错误的 错误的
真的 错误的 真的 错误的 真的
真的 真的 错误的 真的 真的
真的 真的 真的 真的 真的


Ed *_*ton 6

用[多个]双重否定表达您的要求(“如果 CHECK_X 或 CHECK_Y 为假,并且 CHECK_Z 也为假,那么我通知用户条件不满足。 ”)比您表达的情况更难理解和实现它们他们以积极的方式。

避免在您的需求或代码中使用诸如!ornot或比较之类的否定词,并避免在变量名称中使用任何否定术语,因为同样的原因 - 肯定总是比否定更容易理解,如果您没有否定,那么您不能以极其难以理解的双重否定结束。falsenot

这就是你所说的你的要求是:

如果 CHECK_X 或 CHECK_Y 为假且 CHECK_Z 也为假,则我通知用户条件不满足。

我们可以直接将您的需求转换为伪代码:

if ( ((CHECK_X == false) || (CHECK_Y == false)) && (CHECK_Z == false) ); then
    print 'conditions are not met'
else
    conditions are met so do nothing
fi
Run Code Online (Sandbox Code Playgroud)

现在,为了减少负面影响,如果我们首先将if“满足条件”(即正面而不是负面)作为正在测试的条件,那么它就会变成:

if ! ( ((CHECK_X == false) || (CHECK_Y == false)) && (CHECK_Z == false) ); then
    conditions are met so do nothing
else
    print 'conditions are not met'
fi
Run Code Online (Sandbox Code Playgroud)

所以现在我们有了一个if测试,可以让我们进入积极的“满足条件”状态,而不是消极的“条件不满足”状态。现在我们只需要通过分解出领先的“非”运算符,并将与 的比较更改为与 的比较,使if测试本身变得积极而不是消极。!falsetrue

如果我们应用布尔代数将负数移到!最外面的括号内,则条件变为:

if ( !((CHECK_X == false) || (CHECK_Y == false)) || !(CHECK_Z == false) ); then
    conditions are met so do nothing
else
    print 'conditions are not met'
fi
Run Code Online (Sandbox Code Playgroud)

如果我们再次应用相同的方法将第一个移动!到它适用的条件内,我们会得到:

if ( ( !(CHECK_X == false) && !(CHECK_Y == false) ) || !(CHECK_Z == false) ); then
    conditions are met so do nothing
else
    print 'conditions are not met'
fi
Run Code Online (Sandbox Code Playgroud)

我们可以通过将每个更改!...false为来简化true:

if ( ((CHECK_X == true) && (CHECK_Y == true)) || (CHECK_Z == true) ); then
    conditions are met so do nothing
else
    print 'conditions are not met'
fi
Run Code Online (Sandbox Code Playgroud)

现在我们有一个完全积极的if测试,产生积极的结果“满足条件”,因此突然变得非常清楚,您的要求很简单,如果 CHECK_Z 或 CHECK_X 和 CHECK_Y 都为真,则满足条件,否则不满足' t,因此我们可以使用if-else上面的或更简洁的方法轻松实现该要求:

$ cat tst.sh
#!/usr/bin/env bash

testit() {
    [[ (("$CHECK_X" == "TRUE") && ("$CHECK_Y" == "TRUE")) || ("$CHECK_Z" == "TRUE") ]] ||
        printf 'conditions are not met\n'
}

for CHECK_X in TRUE FALSE; do
    for CHECK_Y in TRUE FALSE; do
        for CHECK_Z in TRUE FALSE; do
            printf 'CHECK_X=%s, CHECK_Y=%s, CHECK_Z=%s %s\n' \
                    "$CHECK_X" "$CHECK_Y" "$CHECK_Z" "$(testit)"
        done
    done
done
Run Code Online (Sandbox Code Playgroud)

$ ./tst.sh
CHECK_X=TRUE, CHECK_Y=TRUE, CHECK_Z=TRUE
CHECK_X=TRUE, CHECK_Y=TRUE, CHECK_Z=FALSE
CHECK_X=TRUE, CHECK_Y=FALSE, CHECK_Z=TRUE
CHECK_X=TRUE, CHECK_Y=FALSE, CHECK_Z=FALSE conditions are not met
CHECK_X=FALSE, CHECK_Y=TRUE, CHECK_Z=TRUE
CHECK_X=FALSE, CHECK_Y=TRUE, CHECK_Z=FALSE conditions are not met
CHECK_X=FALSE, CHECK_Y=FALSE, CHECK_Z=TRUE
CHECK_X=FALSE, CHECK_Y=FALSE, CHECK_Z=FALSE conditions are not met
Run Code Online (Sandbox Code Playgroud)