Skip to content

/flags/grep/grep-f-fixed-strings

grep -F: search for a literal string, not a regex

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · grep (GNU grep) 3.0updated
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

bash
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.txt

Output

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.

bash
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.log

Output

order 1001 shipped
order 1003 shipped
--- not in the list
order 1002 pending
OptionPattern syntax
-G (default)Basic regex: . * [ ] ^ $ are special; + ? | need a backslash in GNU grep
-EExtended regex: + ? | ( ) { } are special without backslashes
-FFixed strings: nothing is special
-PPerl-compatible regex (GNU grep built with PCRE)
-xWith -F, the whole line must equal the string
-f FILERead one pattern per line from FILE

Pitfalls

  • Shell quoting still applies. -F stops grep from interpreting the pattern, not the shell. Use single quotes so that $5 or * are not expanded before grep sees them; with a variable write grep -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 -x for whole-line matches and several -e options 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.

Sources