最近甲同事权利代码审查该[[ ]]
构建体是优选的超过[ ]
中样构建体
if [ "`id -nu`" = "$someuser" ] ; then
echo "I love you madly, $someuser"
fi
他无法提供理由。有一个吗?
[[
具有较少的惊喜,并且通常更安全使用。但是它不是可移植的 - POSIX 没有指定它的功能,只有一些 shell 支持它(除了 bash,我听说 ksh 也支持它)。例如,您可以
[[ -e $b ]]
测试文件是否存在。但是,使用[
,必须引用$b
,因为它会拆分参数并扩展诸如"a*"
(其中[[
实际上是接受它的地方)。这还与怎么办[
可外接程序,并接受它的参数通常只是像其他程序(虽然它也可以是一个内置的,但后来仍然没有这种特殊处理)。
[[
还具有其他一些不错的功能,例如与=~
匹配的正则表达式以及类似 C 的语言中已知的运算符。这是一个很好的页面: test, [
和[[
什么区别?和重击测试
Behavior differences
Some differences on Bash 4.3.11:
POSIX vs Bash extension:
[
is POSIX[[
is a Bash extension inspired from Korn shellregular command vs magic
[
is just a regular command with a weird name.
]
is just the last argument of [
.
Ubuntu 16.04 actually has an executable for it at /usr/bin/[
provided by coreutils, but the bash built-in version takes precedence.
Nothing is altered in the way that Bash parses the command.
In particular, <
is redirection, &&
and ||
concatenate multiple commands, ( )
generates subshells unless escaped by \
, and word expansion happens as usual.
[[ X ]]
is a single construct that makes X
be parsed magically. <
, &&
, ||
and ()
are treated specially, and word splitting rules are different.
There are also further differences like =
and =~
.
In Bashese: [
is a built-in command, and [[
is a keyword: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
[[ a < b ]]
: lexicographical comparison[ a \< b ]
: Same as above. \
required or else does redirection like for any other command. Bash extension.expr x"$x" \< x"$y" > /dev/null
or [ "$(expr x"$x" \< x"$y")" = 1 ]
: POSIX equivalents, see: How to test strings for lexicographic less than or equal in Bash?&&
and ||
[[ a = a && b = b ]]
: true, logical and[ a = a && b = b ]
: syntax error, &&
parsed as an AND command separator cmd1 && cmd2
[ a = a ] && [ b = b ]
: POSIX reliable equivalent[ a = a -a b = b ]
: almost equivalent, but deprecated by POSIX because it is insane and fails for some values of a
or b
like !
or (
which would be interpreted as logical operations(
[[ (a = a || a = b) && a = b ]]
: false. Without ( )
, would be true because [[ && ]]
has greater precedence than [[ || ]]
[ ( a = a ) ]
: syntax error, ()
is interpreted as a subshell[ \( a = a -o a = b \) -a a = b ]
: equivalent, but ()
, -a
, and -o
are deprecated by POSIX. Without \( \)
would be true because -a
has greater precedence than -o
{ [ a = a ] || [ a = b ]; } && [ a = b ]
non-deprecated POSIX equivalent. In this particular case however, we could have written just: [ a = a ] || [ a = b ] && [ a = b ]
because the ||
and &&
shell operators have equal precedence unlike [[ || ]]
and [[ && ]]
and -o
, -a
and [
word splitting and filename generation upon expansions (split+glob)
x='a b'; [[ $x = 'a b' ]]
: true, quotes not neededx='a b'; [ $x = 'a b' ]
: syntax error, expands to [ a b = 'a b' ]
x='*'; [ $x = 'a b' ]
: syntax error if there's more than one file in the current directory.x='a b'; [ "$x" = 'a b' ]
: POSIX equivalent=
[[ ab = a? ]]
: true, because it does pattern matching (* ? [
are magic). Does not glob expand to files in current directory.[ ab = a? ]
: a?
glob expands. So may be true or false depending on the files in the current directory.[ ab = a\? ]
: false, not glob expansion=
and ==
are the same in both [
and [[
, but ==
is a Bash extension.case ab in (a?) echo match; esac
: POSIX equivalent[[ ab =~ 'ab?' ]]
: false, loses magic with ''
in Bash 3.2 and above and provided compatibility to bash 3.1 is not enabled (like with BASH_COMPAT=3.1
)[[ ab? =~ 'ab?' ]]
: true=~
[[ ab =~ ab? ]]
: true, POSIX extended regular expression match, ?
does not glob expand[ a =~ a ]
: syntax error. No bash equivalent.printf 'ab\n' | grep -Eq 'ab?'
: POSIX equivalent (single line data only)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
: POSIX equivalent.Recommendation: always use []
There are POSIX equivalents for every [[ ]]
construct I've seen.
如果使用[[ ]]
,则:
[
只是一个具有奇怪名称的常规命令,不涉及任何特殊的语义。感谢StéphaneChazelas 所做的重要更正和补充。
[[ ]]
具有更多功能 - 建议您阅读Advanced Bash 脚本指南,以获取更多信息,尤其是第 7 章中的扩展测试命令部分。测试。
顺便说一句,作为指南, [[ ]]
是在 ksh88(1988 年版本的 Korn shell)中引入的。