Difference between single and double square brackets in Bash
I'm reading bash examples about if but some examples are written with single square brackets:
if [ -f $param ]
then
#...
fi
others with double square brackets:
if [[ $? -ne 0 ]]
then
start looking for errors in yourlog
fi
What is the difference?
Single [] are posix shell compliant condition tests.
Double [[]] are an extension to the standard [] and are supported by bash and other shells (eg zsh, ksh). They support extra operations (as well as the standard posix operations). For example: || instead of -o and regex matching with =~ . A fuller list of differences can be found in the bash manual section on conditional constructs.
Use [] whenever you want your script to be portable across shells. Use [[]] if you want conditional expressions not supported by [] and don't need to be portable.
Behavior differences
Tested in Bash 4.3.11:
POSIX vs Bash extension:
[ is POSIX [[ is a Bash extension regular command vs magic
[ is just a regular command with a weird name.
] is just an argument of [ that prevents further arguments from being used.
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. && and ||
[[ a = a && b = b ]] : true, logical and [ a = a && b = b ] : syntax error, && parsed as an AND command separator cmd1 && cmd2 [ a = a -ab = b ] : equivalent, but deprecated by POSIX [ a = a ] && [ b = b ] : POSIX recommendation (
[[ (a = a || a = b) && a = b ]] : false [ ( a = a ) ] : syntax error, () is interpreted as a subshell [ ( a = a -oa = b ) -aa = b ] : equivalent, but () is deprecated by POSIX ([ a = a ] || [ a = b ]) && [ a = b ] POSIX recommendation word splitting
x='a b'; [[ $x = 'ab' ]] x='a b'; [[ $x = 'ab' ]] : true, quotes not needed x='a b'; [ $x = 'ab' ] x='a b'; [ $x = 'ab' ] : syntax error, expands to [ ab = 'ab' ] x='a b'; [ "$x" = 'ab' ] x='a b'; [ "$x" = 'ab' ] : equivalent =
[[ ab = a? ]] [[ ab = a? ]] : true, because it does pattern matching ( * ? [ are magic). Does not glob expand to files in current directory. [ ab = a? ] [ ab = a? ] : a? glob expands. So may be true or false depending on the files in the current directory. [ ab = a? ] [ ab = a? ] : false, not glob expansion = and == are the same in both [ and [[ , but == is a Bash extension. printf 'ab' | grep -Eq 'a.' : POSIX ERE equivalent [[ ab =~ 'ab?' ]] [[ ab =~ 'ab?' ]] : false, loses magic with '' [[ ab? =~ 'ab?' ]] [[ ab? =~ 'ab?' ]] : true =~
[[ ab =~ ab? ]] [[ ab =~ ab? ]] : true, POSIX extended regular expression match, ? does not glob expand [ a =~ a ] : syntax error printf 'ab' | grep -Eq 'ab?' : POSIX equivalent Recommendation
I prefer to always use [] .
There are POSIX equivalents for every [[ ]] construct I've seen.
If you use [[ ]] you:
[ is just a regular command with a weird name, no special semantics are involved. Inside single brackets for condition test (ie [ ... ]), some operators such as single = is supported by all shells, whereas use of operator == is not supported by some of the older shells.
Inside double brackets for condition test (ie [[ ... ]]), there is no difference between using = or == in old or new shells.
Edit: I should also note that: In bash, always use double brackets [[ ... ]] if possible, because it is safer than single brackets. I'll illustrate why with the following example:
if [ $var == "hello" ]; then
if $var happens to be null / empty, then this is what the script sees:
if [ == "hello" ]; then
which will break your script. The solution is to either use double brackets, or always remember to put quotes around your variables ( "$var" ). Double brackets is better defensive coding practice.
上一篇: 双方括号在bash中的含义
下一篇: Bash中单方括号和双方括号的区别
