Bash 中 [[ ]] AND [ ] 或 (( )) AND ( ) 之间的区别

riz*_*wan 10 linux bash shell-script

[[ condition ]]使用and[ condition ](( condition ))and有什么区别( condition )?在什么场景下我们需要使用这两者?

  • (( 10 > 9 ))有效但(( 10 -gt 9 ))无效
  • [[ 10 -gt 9 ]]有效但[[ 10 > 9 ]]无效

gle*_*man 24

((...))是 shell 的算术结构。您可以使用的运算符记录在手册中:6.5 Shell Arithmetic

(...)是一个分组结构,它执行子 shell 中包含的命令:3.2.4.3 分组命令

[...]是“遗留”条件构造。文档位于6.4 Bash 条件表达式

[[...]]做所有该[...]做的事。不同之处在于,不会对内部变量执行分词和全局扩展[[...]],因此引用变量并不那么重要。此外,还[[可以使用运算符进行模式匹配==和使用运算符进行正则表达式匹配=~

原因是[[ 10 > 9 ]]给你一个意想不到的结果,因为>里面的运算符[[...]]是用于字符串比较的,字符串“10”“小于”字符串“9”。


Kam*_*ski 11

关于((\xe2\x80\xa6))(\xe2\x80\xa6)

\n

正如另一个答案中所述,((\xe2\x80\xa6))是 shell 的算术构造(bashism (\xe2\x80\xa6)在子 shell 中运行命令。它们彼此之间以及[ \xe2\x80\xa6 ]彼此之间都非常不同[[ \xe2\x80\xa6 ]]非常不同。

\n

另一方面,在简单情况下[ \xe2\x80\xa6 ][[ \xe2\x80\xa6 ]]非常相似;他们可能会感到困惑。这个答案的其余部分集中于[ \xe2\x80\xa6 ][[ \xe2\x80\xa6 ]]

\n
\n

正式说明

\n

我的目标是:

\n
    \n
  • 详细说明之间的差异和相似之处[ \xe2\x80\xa6 ][[ \xe2\x80\xa6 ]]
  • \n
  • [ \xe2\x80\xa6 ]在vs的主题中提供规范的答案[[ \xe2\x80\xa6 ]],因此可以通过“回答的问题[不是[[可以链接到此处;
  • \n
  • 提供足够详尽的答案,因此用户不再试图发布只关注单一差异的答案。
  • \n
\n
\n

什么是[

\n
    \n
  1. [执行测试。

    \n

    的目的[是测试某些内容(例如,是否存在某个文件),如果测试成功则返回退出状态零,否则返回非零。

    \n
  2. \n
  3. [是一个命令。

    \n

    [是一个命令名称,例如catecho[(如echo) 是 Bash 中的内置命令,但这仅意味着它可以在不生成额外进程的情况下运行,它的行为仍然类似于命令。[您的系统中可能有一个独立的可执行文件(例如/bin/[);尝试type -a [使用 Bash 来找出答案。

    \n
  4. \n
  5. [后面需要一个空格。

    \n

    作为命令,[需要参数。与任何其他命令一样,参数必须与另一个参数以及命令名称分开。[foo是一个不同的命令名称,它不等于[ foo(类似且更明显的echoHello world是不是echo Hello world)。您肯定需要一个空格(或制表符)[

    \n
  6. \n
  7. [需要].

    \n

    [require]作为最后一个参数,否则它将无法工作。这只是为了让其[ \xe2\x80\xa6 ]作为一个块脱颖而出,就好像它是某种特殊的语法一样;但这不是特殊的语法。要作为最后一个参数传递,]您需要在其前面有一个空格(或制表符)。[ \xe2\x80\xa6 bar]为了比较: is中的最后一个参数bar]is not ],所以[ \xe2\x80\xa6 bar]不是有效的命令。

    \n
  8. \n
  9. [(几乎)就像test.

    \n

    [ \xe2\x80\xa6 ]相当于test \xe2\x80\xa6. 换句话说,您可以通过删除并更改命令名称来将任何[命令转换为命令。并且您可以通过更改命令名称并添加.test]test[]

    \n
  10. \n
  11. [并不特别。

    \n

    最好记住它[并不特殊,它只是命令的一个有点奇特的名称。如果您承认这一点,那么您不会对以下事实感到惊讶:如果命令是 ,则shell 在运行命令(或等)之前所做的所有解析和处理也会发生。尤其:testechols[

    \n
      \n
    • [不知道您是否引用了它的任何参数,它会在 shell 删除引号后获取参数。

      \n
    • \n
    • 未加引号且未转义&&或介于and||之间的内容不被解释为 的参数。换句话说,被解释为(无效,因为没有)和(一个单独的命令,无论是什么)与 逻辑连接,完全相同。[][[ \xe2\x80\xa6 || \xe2\x80\xa6 ][ \xe2\x80\xa6]\xe2\x80\xa6 ]\xe2\x80\xa6||command1 || command2

      \n
    • \n
    \n
  12. \n
  13. [由 POSIX 指定。

    \n

    /POSIX 规范[test。您可以拨打[便携式电话。笔记:

    \n
      \n
    • 一些主要是扩展,一些被标记为过时。例如,我们的无效代码 ( [ \xe2\x80\xa6 || \xe2\x80\xa6 ]) 可以修复为[ \xe2\x80\xa6 -o \xe2\x80\xa6 ],但由于-o已过时,更好的修复方法是[ \xe2\x80\xa6 ] || [ \xe2\x80\xa6 ]
    • \n
    • 实现可能支持更多初选。Bash 中的内置函数[可以做到这一点(请参阅 参考资料help test);您的操作系统中的二进制文件(如 )可能会(请参阅[)。/bin/[man test
    • \n
    \n
  14. \n
\n
\n

什么是[[?与有何[[不同[

\n

注意:
\n - 问题被标记为[[ 在 Bash 中讨论。
\n - 本节中的编号段落与上一节中的编号段落相对应。

\n
    \n
  1. (相似性)[[执行测试。

    \n

    的目的[[是测试某些内容(例如,是否存在某个文件),如果测试成功则返回退出状态零,否则返回非零。[[可以测试任何[可以,甚至更多。\xe2\x80\x8b

    \n
  2. \n
  3. (差异)[[是一个关键字。

    \n

    \xe2\x80\x8b[[是 shell 关键字(type [[在 Bash 中调用以确认这一点)。与[builtin一样,该[[关键字属于Bash;但它的行为并不像命令。

    \n
  4. \n
  5. (相似性)[[后面需要一个空格。

    \n

    (或选项卡)。

    \n
  6. \n
  7. (相似性)[[要求]].

    \n

    [[需要]]稍后在代码中添加,但这不仅仅是为了使[[ \xe2\x80\xa6 ]]代码块脱颖而出。这是一种特殊的语法(有一个区别,我们会讨论它)。之前需要一个空格(或制表符)]]

    \n
  8. \n
  9. (区别)不存在与 等效的普通命令[[

    \n

    没有其他命令/关键字/任何东西可以以可以替换的[[方式替换。test[

    \n
  10. \n
  11. (差异)[[ 特殊的。

    \n

    [[改变 shell 解析和解释代码的方式,直到匹配]]. shell 在运行之前执行的正常解析和处理[or test(或echols)不适用于 inside [[ \xe2\x80\xa6 ]]。尤其:

    \n
      \n
    • [[ 知道您是否引用了它的任何“论点”。双引号变量不是必需的(虽然通常是这样),但在某些情况下,双引号字符串(或变量)会产生影响(请参阅此答案=,其中提到“ or==!=or的右侧=~”) 。

      \n
    • \n
    • &&||之间[[]]属于该[[ \xe2\x80\xa6 ]]构造。[[ \xe2\x80\xa6 || \xe2\x80\xa6 ]]可以是一段有效的代码,实际上相当于[[ \xe2\x80\xa6 ]] || [[ \xe2\x80\xa6 ]].

      \n
    • \n
    \n
  12. \n
  13. (差异)[[未由 POSIX 指定。

    \n

    \xe2\x80\x8b[[不可移植。[[在 Bash 中工作,在 pure 中不起作用sh。其他 shell 可能支持[[(例如 Zsh),但它们[[可能与[[Bash 不同。

    \n

    [[[未设计为符合/的规范test。在许多情况下,替换[with[[]with]]将为您提供[[ \xe2\x80\xa6 ]]与原始[ \xe2\x80\xa6 ]片段等效的片段;但也并非总是如此,有时内部需要调整。所以不要盲目[改变[[。盲目改成[[风险[更大,因为有些测试[[可以做,有些测试[不能做。

    \n
  14. \n
\n
\n

其他注意事项:

\n
    \n
  1. [Nor 都不是语法[[的一部分if \xe2\x80\xa6 then \xe2\x80\xa6。请记住if,仅测试某些代码的退出状态。if true; then \xe2\x80\xa6有效、if sleep 5; then \xe2\x80\xa6有效、类似if [ \xe2\x80\xa6 ]; then \xe2\x80\xa6if [[ \xe2\x80\xa6 ]]; then \xe2\x80\xa6有效(如果[ \xe2\x80\xa6 ][[ \xe2\x80\xa6 ]]部分本身是有效片段)。

    \n

    由于((\xe2\x80\xa6))or(\xe2\x80\xa6)还返回一些退出状态(这取决于里面的内容),因此也可以在之后使用if

    \n
  2. \n
  3. 就我个人而言,我更喜欢使用[任何可以轻松完成的测试,在真正必要时才[使用。[[这样我就不会习惯非可移植性[[,并且我知道我可以在不像 Bash 那样丰富的 shell 中做什么。

    \n
  4. \n
  5. 操作系统中的可执行文件[不一定严格等同于[Bash 中的内置文件。如果[由 Bash 调用,那么内置函数将完成这项工作。如果[被其他东西调用,那么可执行文件将完成这项工作。例如find \xe2\x80\xa6 -exec [ \xe2\x80\xa6 ] \xe2\x80\xa6使用可执行文件。没有标准的[[可执行文件(至少在我知道的系统中),所以find \xe2\x80\xa6 -exec [[ \xe2\x80\xa6 ]] \xe2\x80\xa6永远不会工作。如果有一个[[可执行文件,那么它的行为必须像命令一样,它无法模仿关键字。

    \n
  6. \n
\n