bash中的双方括号和单方括号有什么区别?

0x8*_*x89 509 scripting shell bash posix

我只是想知道两者之间到底有什么区别

[[ $STRING != foo ]]
Run Code Online (Sandbox Code Playgroud)

[ $STRING != foo ]
Run Code Online (Sandbox Code Playgroud)

除此之外,后者是符合 POSIX 的,可在 sh 中找到,而前者是在 bash 中找到的扩展。

Kyl*_*ndt 357

有几个区别。在我看来,最重要的几个是:

  1. [是 Bash 和许多其他现代 shell 中的内置函数。内置[函数类似于test一个关闭的附加要求]。内置函数[test模仿功能/bin/[以及/bin/test它们的限制,以便脚本向后兼容。原始可执行文件仍然存在,主要是为了 POSIX 合规性和向后兼容性。type [在 Bash 中运行该命令表示[默认情况下将其解释为内置命令。(注:which [只查找PATH上的可执行文件,等价于type -P [.type --help详情可以执行)
  2. [[不那么兼容,它不一定适用于任何/bin/sh指向的东西。所以[[是更现代的Bash /岩组/ KSH选项。
  3. 因为[[内置在 shell 中并且没有遗留要求,所以您不必担心基于IFS变量的分词会弄乱评估为带有空格的字符串的变量。因此,您实际上并不需要将变量放在双引号中。

在大多数情况下,其余的只是一些更好的语法。要查看更多差异,我推荐此链接到常见问题解答:test, [ 和 [[ 之间有什么区别?. 事实上,如果您对 bash 脚本很认真,我建议您阅读整个wiki,包括 FAQ、Pitfalls和 Guide。 指南部分的测试部分也解释了这些差异,以及为什么作者认为[[如果您不需要担心便携性是更好的选择。主要原因是:

  1. 您不必担心引用测试的左侧,以便它实际上作为变量被读取。
  2. 您不必< >使用反斜杠转义小于和大于,以便它们不会被评估为输入重定向,这可能会因覆盖文件而真正弄乱一些东西。这又回到[[了内置。如果 [ (test) 是一个外部程序,shell 将不得不在它的评估方式上做出一个例外,<并且>只有在/bin/test被调用时,这才真正有意义。

  • 谢谢,bash FAQ 的链接就是我要找的(不知道那个页面,谢谢)。 (5认同)
  • 我用这些信息编辑了您的帖子,但是 [ 和 test 作为内置函数执行。内置函数旨在替换 /bin/[ 和 /bin/test 但也需要重现二进制文件的局限性。命令“type [”验证是否使用了内置命令。'which [' 只搜索 PATH 上的可执行文件,相当于 'type -P [' (2认同)

小智 151

简而言之:

[ 是一个 bash内置

[[]] 是 bash关键字

关键字:关键字很像内置函数,但主要区别在于它们适用特殊的解析规则。例如, [ 是一个 bash 内置函数,而 [[ 是一个 bash 关键字。它们都用于测试内容,但由于 [[ 是关键字而不是内置函数,它受益于一些特殊的解析规则,使其变得更加容易:

  $ [ a < b ]
 -bash: b: No such file or directory
  $ [[ a < b ]]
Run Code Online (Sandbox Code Playgroud)

第一个示例返回错误,因为 bash 尝试将文件 b 重定向到命令 [ a ]。第二个例子实际上做了你所期望的。字符 < 不再具有文件重定向运算符的特殊含义。

来源:http : //mywiki.wooledge.org/BashGuide/CommandsAndArguments

  • `[` 是一个 POSIX shell 命令;它不需要内置。`]` 只是该命令查找的参数,因此语法是平衡的。该命令是 `test` 的同义词,除了 `test` 不寻找结束的 `]`。 (4认同)

Cir*_*郝海东 96

行为差异

Bash 4.3.11 的一些差异:

  • POSIX 与 Bash 扩展:

  • 常规命令 vs 魔法

    • [ 只是一个带有奇怪名称的常规命令。

      ]只是 的最后一个参数[

    Ubuntu 16.04 实际上有一个/usr/bin/[coreutils提供的可执行文件,但 bash 内置版本优先。

    Bash 解析命令的方式没有任何改变。

    特别<是重定向,&&||连接多个命令,( )除非被 转义\,否则生成子shell ,并且单词扩展照常发生。

    • [[ X ]]是一个单一的构造,X可以神奇地解析。<, &&,||()被特殊对待,分词规则不同。

      还有进一步的差异,例如==~

    在 Bashese 中:[是一个内置命令,[[是一个关键字:https : //askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword

  • <

  • &&||

    • [[ a = a && b = b ]]: 真实的、合乎逻辑的
    • [ a = a && b = b ]: 语法错误,&&解析为 AND 命令分隔符cmd1 && cmd2
    • [ a = a ] && [ b = b ]: POSIX 可靠等价物
    • [ a = a -a b = b ]: 几乎等价,但被 POSIX 弃用,因为它很疯狂并且对于某些值ab类似!(将被解释为逻辑操作失败
  • (

    • [[ (a = a || a = b) && a = b ]]: 错误的。没有( ), 将是真的,因为[[ && ]]具有更高的优先级[[ || ]]
    • [ ( a = a ) ]: 语法错误,()被解释为子shell
    • [ \( a = a -o a = b \) -a a = b ]: 等效,但是()-a-o被 POSIX 弃用。没有\( \)将是真的,因为-a它的优先级高于-o
    • { [ a = a ] || [ a = b ]; } && [ a = b ]未弃用的 POSIX 等效项。然而,在这种特殊情况下,其实我们可以只写:[ a = a ] || [ a = b ] && [ a = b ]因为||&&外壳运营商有不同相同的优先级[[ || ]][[ && ]]-o-a[
  • 扩展时的分词和文件名生成(split+glob)

    • x='a b'; [[ $x = 'a b' ]]: 是的,不需要引号
    • x='a b'; [ $x = 'a b' ]: 语法错误,扩展为 [ a b = 'a b' ]
    • x='*'; [ $x = 'a b' ]: 如果当前目录中有多个文件,则会出现语法错误。
    • x='a b'; [ "$x" = 'a b' ]: POSIX 等价物
  • =

    • [[ ab = a? ]]: 是的,因为它进行模式匹配* ? [很神奇)。不 glob 扩展到当前目录中的文件。
    • [ ab = a? ]: a?glob 扩展。所以根据当前目录中的文件可能为真或假。
    • [ ab = a\? ]: false,不是全局扩展
    • ===在双方的同[[[,不过==是一个bash扩展。
    • case ab in (a?) echo match; esac: POSIX 等价物
    • [[ ab =~ 'ab?' ]]: false,''在 Bash 3.2 及更高版本中失去魔法,并且未启用与 bash 3.1 的兼容性(如 with BASH_COMPAT=3.1
    • [[ ab? =~ 'ab?' ]]: 真的
  • =~

    • [[ ab =~ ab? ]]: true,POSIX扩展正则表达式匹配,?不 glob 扩展
    • [ a =~ a ]: 语法错误。没有 bash 等价物。
    • printf 'ab\n' | grep -Eq 'ab?': POSIX 等价物(仅限单行数据)
    • awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?': POSIX 等价物。

建议:一直使用 []

[[ ]]我见过的每个构造都有 POSIX 等价物。

如果你使用[[ ]]你:

  • 失去便携性
  • 迫使读者了解另一个 bash 扩展的复杂性。[只是一个带有奇怪名称的常规命令,不涉及特殊语义。

感谢Stéphane Chazelas的重要更正和补充。


Pre*_*raj 13

Single Bracket ie[]符合 POSIX shell 以包含条件表达式。

Double Brackets ie[[]]是标准 POSIX 版本的增强(或扩展)版本,bash 和其他 shell(zsh,ksh)支持它。

在bash中,对数字比较,我们使用eqneltgt,与比较双括号,我们可以使用==!=<,>字面。

  • [是测试命令的同义词。即使它内置在外壳中,它也会创建一个新进程。
  • [[ 是它的新改进版,是关键字,不是程序。

例如:

[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory 
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works
Run Code Online (Sandbox Code Playgroud)


wom*_*ble 7

基于对联机帮助页相关部分的快速阅读,主要区别似乎是==and!=运算符与模式匹配,而不是文字字符串,并且还有=~正则表达式比较运算符。