Bash if [false]; 返回true

ten*_*les 129 bash conditional-operator

本周一直在学习bash并陷入困境.

#!/bin/sh

if [ false ]; then
    echo "True"
else
    echo "False"
fi
Run Code Online (Sandbox Code Playgroud)

这将始终输出True,即使条件似乎表示不是这样.如果我删除括号[]然后它工作,但我不明白为什么.

che*_*ner 163

您正在使用参数"false" 运行[(aka test)命令,而不是运行该命令false.由于"false"是非空字符串,因此test命令始终成功.要实际运行该命令,请删除该[命令.

if false; then
   echo "True"
else
   echo "False"
fi
Run Code Online (Sandbox Code Playgroud)

  • `bash`没有布尔数据类型,因此没有表示true和false的关键字.`if`语句只检查你给它的命令是成功还是失败.`test`命令接受表达式并在表达式为真时成功; 非空字符串是一个计算结果为true的表达式,就像在大多数其他编程语言中一样.`false`是一个总是失败的命令.(通过类比,`true`是一个总是成功的命令.) (26认同)
  • 不要将`false`误认为是布尔常数,要么将'0`误认为整数文字; 两者都只是普通的字符串.对于任何不以连字符开头的字符串`x`,`[[x]]`相当于`[[ - nx]]`.`bash`在任何上下文中都没有*any*Boolean常量.看起来像整数的字符串在`((...))`中或在`[[...]]`中使用诸如`-eq`或`-lt`之类的运算符. (7认同)
  • `if [[ false ]];` 也返回 true。就像`if [[ 0 ]];`。并且 `if [[ /usr/bin/false ]];` 也不会跳过该块。false 或 0 如何评估为非零?该死的,这令人沮丧。如果重要的话,OS X 10.8;猛击 3. (4认同)
  • 错误地认为是命令,甚至是字符串的想法对我来说似乎很奇怪,但我想它是可行的。谢谢。 (2认同)
  • @ tbc0,手头上有更多的顾虑,而不仅仅是某些内容.如果变量是由不完全在你控制之下的代码设置的(或者可以通过异常文件名或其他方式在外部操作),`if $ predicate`很容易被滥用来执行恶意代码,如果[if [[$谓词]]`不能. (2认同)
  • “false”是无条件产生退出状态 1 的命令。 (2认同)

Bee*_*jor 42

Bash的快速布尔入门

if声明需要一个命令作为参数(如做&&,||等).该命令的整数结果代码被解释为布尔值(0/null = true,1/else = false).

test语句将运算符和操作数作为参数,并以与格式相同的格式返回结果代码if.该test语句的别名,[通常用于if执行更复杂的比较.

truefalse语句什么也不做,返回的结果代码(0和1,分别).所以它们可以在Bash中用作布尔文字.但是如果你把语句放在一个被解释为字符串的地方,你就会遇到问题.在你的情况下:

if [ foo ]; then ... # "if the string 'foo' is non-empty, return true"
if foo; then ...     # "if the command foo succeeds, return true"
Run Code Online (Sandbox Code Playgroud)

所以:

if [ true  ] ; then echo "This text will always appear." ; fi;
if [ false ] ; then echo "This text will always appear." ; fi;
if true      ; then echo "This text will always appear." ; fi;
if false     ; then echo "This text will never appear."  ; fi;
Run Code Online (Sandbox Code Playgroud)

这类似于做类似echo '$foo'对战echo "$foo".

使用该test语句时,结果取决于使用的运算符.

if [ "$foo" = "$bar" ]   # true if the string values of $foo and $bar are equal
if [ "$foo" -eq "$bar" ] # true if the integer values of $foo and $bar are equal
if [ -f "$foo" ]         # true if $foo is a file that exists (by path)
if [ "$foo" ]            # true if $foo evaluates to a non-empty string
if foo                   # true if foo, as a command/subroutine,
                         # evaluates to true/success (returns 0 or null)
Run Code Online (Sandbox Code Playgroud)

简而言之,如果您只想测试通过/失败(也称为"true"/"false"),则将命令传递给您if&&等语句,不带括号.对于复杂的比较,请使用括号和适当的运算符.

是的,我知道在Bash中没有本地布尔类型if,[而且true在技​​术上是"命令"而不是"语句"; 这只是一个非常基本的功能性解释.

  • 仅供参考,如果你想在你的代码中使用 1/0 作为 True/False,这个 `if (( $x )); 然后回声“你好”;fi` 显示 `x=1` 的消息,但不显示 `x=0` 或 `x=`(未定义)的消息。 (3认同)

小智 7

我发现我可以通过运行以下命令来执行一些基本逻辑:

A=true
B=true
if ($A && $B); then
    C=true
else
    C=false
fi
echo $C
Run Code Online (Sandbox Code Playgroud)

  • 一个*可以*,但这是一个非常糟糕的主意。`( $A && $B )` 是一个令人惊讶的低效操作 - 您通过调用 `fork()` 生成一个子进程,然后对 `$A` 的内容进行字符串分割以生成元素列表(在此大小为 1 的情况),并将每个元素作为一个 glob 进行评估(在本例中评估为自身),然后将结果作为命令运行(在本例中为内置命令)。 (9认同)
  • 写成“A=1”会安全得多,**多**;B=1` 和 `if (( A && B ))` - 将它们视为数字 - 或 `[[ $A && $B ]]`,将空字符串视为 false,将非空字符串视为真的。 (9认同)
  • (请注意,我仅使用上面的全大写变量名来遵循答案建立的约定 - POSIX 实际上[明确指定](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html ) 用于环境变量和 shell 内置函数的全大写名称,并保留小写名称供应用程序使用;为了避免与未来的操作系统环境发生冲突,特别是考虑到设置 shell 变量会覆盖任何类似命名的环境变量,最好在自己的脚本中遵守该约定)。 (5认同)
  • 此外,如果您的“true”和“false”字符串来自其他地方,则存在它们实际上可能包含“true”或“false”以外的内容的风险,并且您可能会出现意外行为,包括任意命令执行。 (3认同)