/errors/grep/unmatched-bracket
grep: Unmatched [, [^, [:, [., or [=
- tool
- grep
- exit code
- 2
- versions
- GNU grep 3.x
- os
- linux, macos, windows
GNU grep reports grep: Unmatched [, [^, [:, [., or [= when the pattern contains an opening [ with no closing ]. In a regular expression [ starts a bracket expression such as [a-z], so grep '[ERROR' is an invalid regex and grep exits with status 2. To search for the bracket itself, use grep -F (fixed string) or escape it as \[.
Reproduce it
printf '[ERROR] disk full\n[INFO] ok\n' > app.log
grep '[ERROR' app.logOutput · exit 2
grep: Unmatched [, [^, [:, [., or [=
Fix: search for a fixed string
printf '[ERROR] disk full\n[INFO] ok\n' > app.log
grep -F '[ERROR' app.log
grep '\[ERROR' app.log
grep -c '^\[[A-Z]*\]' app.logOutput
[ERROR] disk full [ERROR] disk full 2
-F turns off regex interpretation entirely. \[ escapes only the bracket. Keep the pattern in single quotes, so the shell passes the backslash to grep unchanged.
The same problem with parentheses
With grep -E (extended regex), ( opens a group, and a lone one fails in the same way:
echo 'f(x)' | grep -E 'f('Output · exit 2
grep: Unmatched ( or \(
Use grep -F 'f(' or grep -E 'f\('. In basic regex (plain grep) ( is literal and \( starts a group, the opposite of -E.