bash - if 语句中的括号有什么作用?

dkv*_*dkv 6 linux bash control-flow test

也许这不仅仅适用于 bash,但我对括号在 if 语句中的作用感到困惑。大多数示例似乎具有以下格式

if [ expression ]; then
    #do stuff
fi
Run Code Online (Sandbox Code Playgroud)

但这并不总是对我有用。例如,我有以下脚本test.sh

#!/bin/bash

flag=False
if ! $flag; then
    echo "No brackets: Flag is $flag"
fi
if [ ! $flag ]; then
    echo "With brackets: Flag is $flag"
fi
echo "The end."
Run Code Online (Sandbox Code Playgroud)

哪个打印

$ ./test.sh
No brackets: Flag is False
The end.
Run Code Online (Sandbox Code Playgroud)

所以使用方括号的语句要么被忽略,要么被评估为 False。为什么会发生这种情况?括号有什么作用?

我也见过双括号。那些是怎么用的?

——

编辑:声称重复的问题(这个这个)只回答了这个问题的一小部分。我仍然不清楚为什么带括号的语法会失败(在我看来test ! false应该计算为true)以及为什么没有括号的语法会成功(尽管正如@ilkkachu 在评论中提到的,它似乎实际上也应该失败? )。

Kus*_*nda 4

在除具有不区分大小写的文件系统(如 macOS)之外的任何 Unix 上,该if语句

if ! $flag; then
    echo "No brackets: Flag is $flag"
fi
Run Code Online (Sandbox Code Playgroud)

将生成输出

bash: False: command not found
No brackets: Flag is False
Run Code Online (Sandbox Code Playgroud)

在 macOS 上,由于文件系统不区分大小写,因此不会生成该错误,因为该False命令与标准(外部)命令相同。false

无论哪种情况,测试! $flag都是正确的(但出于不同的原因),因此文本被打印。在大多数 Unices 上,! $flag为 true,因为它运行False命令,失败,并且失败被否定。在 macOS 上,它运行外部false实用程序,该实用程序返回 false,即否定。

第二个if声明,

if [ ! $flag ]; then
    echo "With brackets: Flag is $flag"
fi
Run Code Online (Sandbox Code Playgroud)

在任何 Unix 上都以相同的方式工作。它使用两个参数和来调用[实用程序,该实用程序与实用程序相同test(但[需要匹配]作为其最后一个操作数)。默认情况下,如果字符串参数具有非零长度(它具有非零长度),则将返回 true 值,但它会被so返回 false 否定,并且永远不会执行。!Falsetest!testecho

为了清楚起见,最好使用-n测试来测试非空字符串:

if [ -n "$flag" ]; then ...
Run Code Online (Sandbox Code Playgroud)

-z测试空字符串:

if [ -z "$flag" ]; then ...
Run Code Online (Sandbox Code Playgroud)

变量扩展的引用在这段特定的代码中并不重要,因为$flag扩展为不是文件名通配模式的单个单词。但一般来说,变量扩展应该用双引号引起来,以避免分词和文件名通配。

[有关vs.的讨论[[,请参阅

有关的: