[[ ]] Extended Test Operator
[[ ]] is Bash's improved version of [ ] that is more forgiving about quoting and adds extra features like pattern matching and regular expressions.In this page:
[[ ]] Basics and Safer Quoting
[[ expression ]] behaves like [ ] for basic comparisons but is more forgiving: unquoted variables inside it are not subject to word splitting or globbing, which avoids many [ ] pitfalls. It is a Bash keyword, not a separate command, so its parsing rules differ from [ ].
Example: [[ ]] Basics and Safer Quoting
#!/bin/bash
name=""
if [[ $name = "" ]]; then
echo "name is empty, and this worked without quoting"
fi
Login to try C/C++/Java/PHP code in the editor
Logical Operators Inside [[ ]]
[[ ]] allows && and || directly inside the double brackets to combine multiple conditions in one expression, which is cleaner than [ ]'s reliance on -a/-o (which are also deprecated). This makes compound conditions much more readable.
Example: Logical Operators Inside [[ ]]
#!/bin/bash
age=25
has_id=true
if [[ $age -ge 18 && $has_id = true ]]; then
echo "Entry allowed"
fi
Login to try C/C++/Java/PHP code in the editor
Glob Pattern Matching with ==
Inside [[ ]], an unquoted pattern on the right side of == or != is matched as a glob (wildcard) pattern rather than a literal string, so * matches any sequence of characters. Quoting the pattern turns off this special matching and forces a literal comparison instead.
Example: Glob Pattern Matching with ==
#!/bin/bash
filename="report.txt"
if [[ $filename == *.txt ]]; then
echo "It's a text file"
fi
if [[ $filename == "*.txt" ]]; then
echo "This won't print, because the pattern is quoted (literal)"
fi
Login to try C/C++/Java/PHP code in the editor
Regex Matching with =~
[[ str =~ regex ]] tests str against a POSIX extended regular expression, and if it matches, the full match and any parenthesized capture groups are stored in the BASH_REMATCH array (BASH_REMATCH[0] is the whole match, [1] the first group, etc.). The regex itself should generally be left unquoted or stored in a variable first for portability.
Example: Regex Matching with =~
#!/bin/bash
email="[email protected]"
if [[ $email =~ ^([a-z]+)@([a-z.]+)$ ]]; then
echo "Full match: ${BASH_REMATCH[0]}"
echo "Username: ${BASH_REMATCH[1]}"
echo "Domain: ${BASH_REMATCH[2]}"
fi
Login to try C/C++/Java/PHP code in the editor
- Assuming
[[ ]]is fully POSIX-portable like[ ]; it is a Bash (and some other modern shells') extension, so scripts meant to run under plainshshould stick to[ ]. - Forgetting that inside
[[ ]],<and>really do compare strings alphabetically without needing escaping (unlike inside[ ]where they redirect); numeric comparison still needs-lt/-gtetc. - Quoting the pattern on the right side of
==when using it for glob matching, e.g.[[ $file == "*.txt" ]]; quoting turns it into a literal string comparison instead of a wildcard match.
[[ ]]does not word-split or glob-expand unquoted variables inside it, so[[ $name = value ]]is safe even without quotes.[[ ]]supports&&and||directly inside the brackets, unlike[ ]which needs-a/-oor separate test invocations.[[ str == pattern ]]supports glob-style wildcard matching when the right-hand pattern is unquoted.[[ str =~ regex ]]performs POSIX extended regular expression matching, storing captured groups in theBASH_REMATCHarray.
Chapter Quiz — Complete all 14 topics to unlock
0/14 topics done
Complete these topics first: