HOWTO · Linux

How to Use Grep With Multiple Strings

This article shows how to use grep to find lines containing one or more patterns.

On this page

For a short list of literal strings, use grep -F with a separate -e option for each pattern. For a newline-separated list stored in a file, use grep -F -f patterns.txt. In either form, grep prints a line when it matches any listed pattern. These commands are useful for searching a file or text sent through standard input from another program.

Both Bash examples below were run: the first prints the warning and error lines from the file, and the second prints the matching error line from standard input.

Using grep to Capture Simple Phrases

By default, grep searches for a substring, so the pattern word also matches a longer string such as sword. The following self-contained Bash example creates a small log and searches it for either of two literal phrases. -F makes punctuation in a pattern literal, while repeated -e options keep the patterns separate and readable.

work_dir=$(mktemp -d)
trap 'rm -rf "$work_dir"' EXIT
printf '%s\n' 'INFO service ready' 'WARN disk almost full' 'ERROR request failed' > "$work_dir/app.log"
grep -F -e 'WARN disk' -e 'ERROR request' "$work_dir/app.log"
WARN disk almost full
ERROR request failed

To search command output instead of a file, pipe the text to grep. This example feeds two lines directly to the search, so it has no dependency on a separate input file:

printf '%s\n' 'INFO service ready' 'ERROR request failed' | grep -F -e 'ERROR' -e 'WARN'
ERROR request failed

The options -w and -x change what counts as a match. -w selects a match that forms a whole word according to grep’s word-character rules; it does not require an exact phrase or particular spaces around the text. -x requires the entire input line to match the pattern. For example, grep -w 'word' file.txt can match word in a line containing other words, while grep -Fx 'word' file.txt matches only a line whose complete content is word. With -F, punctuation is treated literally in either case.

grep With Multiple Strings

When the list grows or changes often, put one pattern on each line of a pattern file and pass the file with -f. This self-contained Bash example creates both the pattern file and the log in a temporary directory, then passes their actual paths to grep:

work_dir=$(mktemp -d)
trap 'rm -rf "$work_dir"' EXIT
printf '%s\n' 'WARN disk' 'ERROR request' > "$work_dir/patterns.txt"
printf '%s\n' 'INFO service ready' 'WARN disk almost full' 'ERROR request failed' > "$work_dir/app.log"
grep -F -f "$work_dir/patterns.txt" "$work_dir/app.log"
WARN disk almost full
ERROR request failed

grep -F -f checks each input line against both literal patterns and prints lines matching either one. Passing the pattern file directly avoids shell quoting and newline-construction problems.

A dollar sign by itself does not separate patterns with a newline. If you need to place multiple patterns in one shell argument, that argument must contain actual newline characters. Repeated -e options are clearer for a short list, and -f is usually easier to maintain for a longer list. Remember that multiple patterns mean “match any”; use a regular expression with lookaheads only when you need to require multiple terms on the same line.

grep With RegEx

Use -E for extended regular expressions, including alternation. For example, grep -E 'apple|banana|grape' fruit.txt matches a line containing at least one of those alternatives. This is still an any-match search: the expression does not require every fruit name to appear. Use -F instead when the patterns should be interpreted as literal text rather than regular-expression syntax.

Some grep implementations also support -P for Perl-compatible regular expressions. On a system with -P support, a lookahead pattern such as ^(?=.*apple)(?=.*banana)(?=.*grape) can require all three terms somewhere on a line. -E does not provide PCRE lookaheads, and -P is not available in every grep build, so check the local grep manual before relying on it. A pattern such as [^@]+@[^.]+.* can illustrate a rough email-shaped match, but it is incomplete and should not be used as an email validator.

For filtering text, grep is often enough; awk or sed may suit a larger transformation task. See the grep manual page for additional options and implementation details.