[ a = a && b = b ]: 语法错误,&&解析为 AND 命令分隔符cmd1 && cmd2
[ a = a ] && [ b = b ]: POSIX 可靠等价物
[ a = a -a b = b ]a: 几乎等价,但被 POSIX 弃用,因为它是疯狂的,并且对于or blike !or的某些值会失败,或者(将被解释为逻辑操作
(
[[ (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 ]因为||和&&shell 运算符具有相同的优先级,不像[[ || ]]and[[ && ]]和-o, -aand[
扩展时的分词和文件名生成 (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,不是全局扩展
=and在and==中是相同的,但是是一个 Bash 扩展。[[[==
case ab in (a?) echo match; esac: POSIX 等价物
[[ ab =~ 'ab?' ]]: false,''在 Bash 3.2 及更高版本中失去魔力,并且未启用对 bash 3.1 的兼容性(如 with BASH_COMPAT=3.1)
有几个不同之处。在我看来,最重要的几个是:
[
是 Bash 和许多其他现代 shell 中的内置函数。内置[
函数类似于test
关闭的附加要求]
。内置函数[
和test
模仿功能/bin/[
以及/bin/test
它们的限制,以便脚本向后兼容。最初的可执行文件仍然存在,主要是为了 POSIX 合规性和向后兼容性。在 Bash 中运行该命令type [
表示[
默认情况下将其解释为内置命令。(注:只在PATHwhich [
上查找可执行文件,相当于.可以执行查看详情)type -P [
type --help
[[
不兼容,它不一定适用于任何/bin/sh
指向。[[
更现代的 Bash / Zsh / Ksh 选项也是如此。[[
内置在 shell 中并且没有遗留要求,所以您无需担心基于IFS变量的分词会弄乱评估为带有空格的字符串的变量。因此,您实际上不需要将变量放在双引号中。在大多数情况下,其余的只是一些更好的语法。要查看更多差异,我推荐此链接到常见问题解答:测试、[ 和 [[ 之间有什么区别?. 事实上,如果您对 bash 脚本很认真,我建议您阅读整个wiki,包括 FAQ、Pitfalls和 Guide。 指南部分的测试部分也解释了这些差异,以及为什么作者认为
[[
如果您不需要担心便携性是更好的选择。主要原因是:< >
使用反斜杠转义小于和大于,以免它们被评估为输入重定向,这可能会通过覆盖文件而真正搞砸一些东西。这又回到[[
了内置。如果 [ (test) 是一个外部程序,那么 shell 将不得不以它的评估方式进行异常处理,<
并且>
只有在/bin/test
被调用时才会发生异常,这实际上没有任何意义。简而言之:
关键字:关键字很像内置函数,但主要区别在于特殊的解析规则适用于它们。例如, [ 是 bash 内置函数,而 [[ 是 bash 关键字。它们都用于测试东西,但由于 [[ 是关键字而不是内置的,它受益于一些特殊的解析规则,这使得它更容易:
第一个示例返回错误,因为 bash 尝试将文件 b 重定向到命令 [ a ]。第二个例子实际上做了你所期望的。字符 < 不再具有文件重定向运算符的特殊含义。
资料来源: http: //mywiki.wooledge.org/BashGuide/CommandsAndArguments
行为差异
Bash 4.3.11 的一些区别:
POSIX 与 Bash 扩展:
[
是 POSIX[[
是一个受 Korn shell 启发的 Bash 扩展常规命令与魔法
[
只是一个带有奇怪名称的常规命令。]
只是 的最后一个参数[
。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 ]
: 同上。\
required 或者像任何其他命令一样进行重定向。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 ]
a
: 几乎等价,但被 POSIX 弃用,因为它是疯狂的,并且对于orb
like!
or的某些值会失败,或者(
将被解释为逻辑操作(
[[ (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 ]
因为||
和&&
shell 运算符具有相同的优先级,不像[[ || ]]
and[[ && ]]
和-o
,-a
and[
扩展时的分词和文件名生成 (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,不是全局扩展=
and在and==
中是相同的,但是是一个 Bash 扩展。[
[[
==
case ab in (a?) echo match; esac
: POSIX 等价物[[ ab =~ 'ab?' ]]
: false,''
在 Bash 3.2 及更高版本中失去魔力,并且未启用对 bash 3.1 的兼容性(如 withBASH_COMPAT=3.1
)[[ ab? =~ 'ab?' ]]
: 真的=~
[[ ab =~ ab? ]]
: true,POSIX扩展正则表达式匹配,?
不全局扩展[ a =~ a ]
: 语法错误。没有 bash 等价物。printf 'ab\n' | grep -Eq 'ab?'
: POSIX 等效项(仅单行数据)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
: POSIX 等价物。建议:一直使用
[]
[[ ]]
我见过的每个构造都有 POSIX 等价物。如果你使用
[[ ]]
你:[
只是一个名称怪异的常规命令,不涉及特殊语义。感谢Stéphane Chazelas的重要更正和补充。
Single Bracket ie
[]
是符合 POSIX shell 的,用于包含条件表达式。双括号ie
[[]]
是标准 POSIX 版本的增强(或扩展)版本,这由 bash 和其他 shell(zsh,ksh)支持。在 bash 中,我们使用
eq
,ne
,lt
and进行数值比较gt
,用双括号进行比较我们可以使用==
,!=
,<,
和>
字面意思。[
是测试命令的同义词。即使它内置在 shell 中,它也会创建一个新进程。[[
是它的新改进版本,它是一个关键字,而不是一个程序。例如:
基于对手册页相关部分的快速阅读,主要区别似乎是
==
and!=
运算符匹配模式,而不是文字字符串,并且还有=~
正则表达式比较运算符。