Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to find all lines in several files that match one of two patterns. I tried to find the patterns I'm looking for by typing

grep (foo|bar) *.txt

but the shell interprets the | as a pipe and complains when bar isn't an executable.

How can I grep for multiple patterns in the same set of files?

share|improve this question
up vote 237 down vote accepted

First, you need to protect the pattern from expansion by the shell. The easiest way to do that is to put single quotes around it. Single quotes prevent expansion of anything between them (including backslashes); the only thing you can't do then is have single quotes in the pattern.

grep 'foo*' *.txt

If you do need a single quote, you can write it as '\'' (end string literal, literal quote, open string literal).

grep 'foo*'\''bar' *.txt

Second, grep supports two syntaxes for patterns. The old, default syntax (basic regular expressions) doesn't support the alternation (|) operator, though some versions have it as an extension, but written with a backslash.

grep 'foo\|bar' *.txt

The portable way is to use the newer syntax, extended regular expressions. You need to pass the -E option to grep to select it. On Linux, you can also type egrep instead of grep -E (on other unices, you can make that an alias).

grep -E 'foo|bar' *.txt

Another possibility when you're just looking for any of several patterns (as opposed to building a complex pattern using disjunction) is to pass multiple patterns to grep. You can do this by preceding each pattern with the -e option.

grep -e foo -e bar *.txt
share|improve this answer
As a sidenote -- when the patterns are fixed, you should really get into the habit of fgrep or grep -F, for small patterns the difference will be negligible but as they get longer, the benefits start to show... – TC1 Apr 26 '12 at 9:37
@TC1, yeah, people often forget that grep uses regexp syntax — unix.stackexchange.com/questions/21020/… – poige Apr 27 '12 at 2:23
@TC1 fgrep is deprecated according to man page – ramn Jul 22 '14 at 8:41
@TC1 Whether grep -F has an actual performance benefit depends on the grep implementation: some of them apply the same algorithm anyway, so that -F makes a difference only to the time spent parsing the pattern and not to the time searching. GNU grep isn't faster with -F, for example (it also has a bug that makes grep -F slower in multibyte locales — the same constant pattern with grep is actually significantly faster!). On the other hand BusyBox grep does benefit a lot from -F on large files. – Gilles Jul 22 '14 at 8:53
Perhaps it should be mentioned that for more complicated patterns where alternation is only to be for a part of the regular expression, it can be grouped with "\(" and "\)" (the escaping is for the default "basic regular expressions") (?). – Peter Mortensen May 20 '15 at 9:45
egrep "foo|bar" *.txt


grep "foo\|bar" *.txt
grep -E "foo|bar" *.txt

selectively citing the man page of gnu-grep:

   -E, --extended-regexp
          Interpret PATTERN as an extended regular expression (ERE, see below).  (-E is specified by POSIX.)

Matching Control
   -e PATTERN, --regexp=PATTERN
          Use PATTERN as the pattern.  This can be used to specify multiple search patterns, or to protect  a  pattern
          beginning with a hyphen (-).  (-e is specified by POSIX.)


   grep understands two different versions of regular expression syntax: “basic” and “extended.”  In  GNU grep,  there
   is  no  difference  in  available  functionality  using  either  syntax.   In  other implementations, basic regular
   expressions are less powerful.  The following description applies to extended regular expressions; differences  for
   basic regular expressions are summarized afterwards.

In the beginning I didn't read further, so I didn't recognize the subtle differences:

Basic vs Extended Regular Expressions
   In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead  use  the
   backslashed versions \?, \+, \{, \|, \(, and \).

I always used egrep and needlessly parens, because I learned from examples. Now I learned something new. :)

share|improve this answer

Like TC1 said, -F seems to be usable option:

$> cat text
some text
another text
end of file

$> patterns="foo

$> grep -F "${patterns}" text
share|improve this answer
+= poige.livejournal.com/514918.html – poige Apr 27 '12 at 2:24
@poige I didn't know about the $'foo\nbar' option, not sure how expansion works here, need to look up, but thank you, that is really useful. – haridsv Nov 5 '12 at 12:26

Firstly, you need to use quoting for special characters. Second, even so grep will not understand alternation directly; you would need to use egrep, or (with GNU grep only) grep -E.

egrep 'foo|bar' *.txt

(The parentheses are unnecessary unless the alternation is part of a larger regex.)

share|improve this answer
Actually, grep -E is more standard than egrep. – jw013 Apr 26 '12 at 1:14

I had access logs where the dates where stupidly formatted : [30/Jun/2013:08:00:45 +0200]

but I needed to display it as : 30/Jun/2013 08:00:45

The problem is that using "OR" in my grep statement, I was receiving the 2 match expressions on 2 separated lines.

Here is the solution :

grep -in myURL_of_interest  *access.log  | \
grep -Eo '(\b[[:digit:]]{2}/[[:upper:]][[:lower:]]{2}/[[:digit:]]{4}|[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}\b)'   \
| paste - - -d" " > MyAccess.log

I hope it helps :)

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.