/flags/grep/grep-f-fixed-strings
grep -F: search for a literal string, not a regex
- tool
- grep
- command
- grep
- flag
- -F, --fixed-strings
- default
- off (the pattern is a basic regular expression)
grep -F 'a.b' file searches for the exact characters a.b; without -F the dot means "any character", so axb matches too. -F (--fixed-strings) turns off regular expressions completely: ., *, [, $, ^ and \ are ordinary characters. Use it whenever the search text comes from a variable, a log line or a list of IDs, so that special characters cannot change the meaning or break the search.
Regex vs literal
printf 'a.b\naxb\n1+1=2\n[x]\nprice $5\n' > data.txt
grep 'a.b' data.txt
echo '--- -F a.b'
grep -F 'a.b' data.txt
echo '--- [x] as regex, then literal'
grep '[x]' data.txt
grep -F '[x]' data.txt
echo '--- $5 literal'
grep -F '$5' data.txtOutput
a.b axb --- -F a.b a.b --- [x] as regex, then literal axb [x] [x] --- $5 literal price $5
As a regex, [x] is a bracket expression that matches any line containing x. With -F only the literal [x] line matches. A lone [ in a regex fails with the Unmatched bracket error; with -F it is just a character.
Many strings at once
-F is efficient with long lists: each line of a -f FILE is one literal string, and a line matches if it contains any of them.
printf 'order 1001 shipped\norder 1002 pending\norder 1003 shipped\n' > orders.log
printf '1001\n1003\n' > ids.txt
grep -F -f ids.txt orders.log
echo '--- not in the list'
grep -vF -f ids.txt orders.logOutput
order 1001 shipped order 1003 shipped --- not in the list order 1002 pending
Related options
| Option | Pattern syntax |
|---|---|
| -G (default) | Basic regex: . * [ ] ^ $ are special; + ? | need a backslash in GNU grep |
| -E | Extended regex: + ? | ( ) { } are special without backslashes |
| -F | Fixed strings: nothing is special |
| -P | Perl-compatible regex (GNU grep built with PCRE) |
| -x | With -F, the whole line must equal the string |
| -f FILE | Read one pattern per line from FILE |
Pitfalls
- Shell quoting still applies.
-Fstops grep from interpreting the pattern, not the shell. Use single quotes so that$5or*are not expanded before grep sees them; with a variable writegrep -F -- "$needle" file. - Newlines separate patterns. A string that contains a newline is treated as several patterns, each of which can match.
- An empty pattern matches every line.
grep -F "$var"with an empty variable prints the whole file; check the variable first. - Regex-only features disappear. Anchors like
^and alternation with|are literal under-F. Use-xfor whole-line matches and several-eoptions for alternatives.
-F is defined by POSIX and behaves the same in GNU grep, BSD grep and BusyBox.
FAQ
What is fgrep?
fgrep is the old name for grep -F. GNU grep 3.8 and later print a warning that fgrep is obsolescent; write grep -F in scripts.
Does grep -F work with -i, -w and -x?
Yes. -F only changes how the pattern is interpreted. -i makes the literal comparison case-insensitive, -w requires whole words and -x requires the whole line to equal the string.
How do I search for a string that starts with a dash?
Put -e before it or end the options with --, for example grep -F -e '-v' file or grep -F -- '-v' file. Otherwise grep reads the string as an option.