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
有几个区别。在我看来,最重要的几个是:
[是 Bash 和许多其他现代 shell 中的内置函数。内置[函数类似于test一个关闭的附加要求]。内置函数[和test模仿功能/bin/[以及/bin/test它们的限制,以便脚本向后兼容。原始可执行文件仍然存在,主要是为了 POSIX 合规性和向后兼容性。type [在 Bash 中运行该命令表示[默认情况下将其解释为内置命令。(注:which [只查找PATH上的可执行文件,等价于type -P [.type --help详情可以执行)[[不那么兼容,它不一定适用于任何/bin/sh指向的东西。所以[[是更现代的Bash /岩组/ KSH选项。[[内置在 shell 中并且没有遗留要求,所以您不必担心基于IFS变量的分词会弄乱评估为带有空格的字符串的变量。因此,您实际上并不需要将变量放在双引号中。在大多数情况下,其余的只是一些更好的语法。要查看更多差异,我推荐此链接到常见问题解答:test, [ 和 [[ 之间有什么区别?. 事实上,如果您对 bash 脚本很认真,我建议您阅读整个wiki,包括 FAQ、Pitfalls和 Guide。 指南部分的测试部分也解释了这些差异,以及为什么作者认为[[如果您不需要担心便携性是更好的选择。主要原因是:
< >使用反斜杠转义小于和大于,以便它们不会被评估为输入重定向,这可能会因覆盖文件而真正弄乱一些东西。这又回到[[了内置。如果 [ (test) 是一个外部程序,shell 将不得不在它的评估方式上做出一个例外,<并且>只有在/bin/test被调用时,这才真正有意义。小智 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
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 < b ]]: 字典比较[ a \< b ]: 和上面一样。\需要或者像任何其他命令一样进行重定向。Bash 扩展。expr x"$x" \< x"$y" > /dev/null或[ "$(expr x"$x" \< x"$y")" = 1 ]:POSIX 等效项,请参阅:https : //stackoverflow.com/questions/21294867/how-to-test-strings-for-lexicographic-less-than-or-equal-in-bash/52707989#52707989&& 和 ||
[[ a = a && b = b ]]: 真实的、合乎逻辑的和[ a = a && b = b ]: 语法错误,&&解析为 AND 命令分隔符cmd1 && cmd2[ a = a ] && [ b = b ]: POSIX 可靠等价物[ a = a -a b = b ]: 几乎等价,但被 POSIX 弃用,因为它很疯狂并且对于某些值a或b类似!或(将被解释为逻辑操作失败(
[[ (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 等价物。
如果你使用[[ ]]你:
[只是一个带有奇怪名称的常规命令,不涉及特殊语义。感谢Stéphane Chazelas的重要更正和补充。
Pre*_*raj 13
Single Bracket ie[]符合 POSIX shell 以包含条件表达式。
Double Brackets ie[[]]是标准 POSIX 版本的增强(或扩展)版本,bash 和其他 shell(zsh,ksh)支持它。
在bash中,对数字比较,我们使用eq,ne,lt和gt,与比较双括号,我们可以使用==,!=,<,和>字面。
[是测试命令的同义词。即使它内置在外壳中,它也会创建一个新进程。[[ 是它的新改进版,是关键字,不是程序。 例如:
[ 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)