52

I need to return results for two different matches from a single file.

grep "string1" my.file

correctly returns the single instance of string1 in my.file

grep "string2" my.file

correctly returns the single instance of string2 in my.file

but

grep "string1|string2" my.file

returns nothing

in regex test apps that syntax is correct, so why does it not work for grep in cygwin ?

Eric Wilson
  • 57,719
  • 77
  • 200
  • 270
rob
  • 8,134
  • 8
  • 58
  • 68

4 Answers4

77

Using the | character without escaping it in a basic regular expression will only match the | literal. For instance, if you have a file with contents

string1
string2
string1|string2

Using grep "string1|string2" my.file will only match the last line

$ grep "string1|string2" my.file
string1|string2

In order to use the alternation operator |, you could:

  1. Use a basic regular expression (just grep) and escape the | character in the regular expression

    grep "string1\|string2" my.file

  2. Use an extended regular expression with egrep or grep -E, as Julian already pointed out in his answer

    grep -E "string1|string2" my.file

  3. If it is two different patterns that you want to match, you could also specify them separately in -e options:

    grep -e "string1" -e "string2" my.file

You might find the following sections of the grep reference useful:

Community
  • 1
  • 1
Xavi López
  • 27,550
  • 11
  • 97
  • 161
  • that works but I expected the sequence to escape the functionality of the pipe rendering it as an ascii pipe character so the regex would be looking for "string1|string2" not doing an or between them – rob Oct 24 '11 at 13:42
  • 6
    As @Julian already pointed out, if you're using metacharacters like `|`, `+`, `?`, and `()` and expect them to work properly without escaping them (as in a normal regexp), you should be using `egrep`. For instance, `egrep "string1|string2"` does the OR. You can still use `grep` if you escape the `|` metacharacter. – Xavi López Oct 24 '11 at 14:12
10

You may need to either use egrep or grep -E. The pipe OR symbol is part of 'extended' grep and may not be supported by the basic Cygwin grep.

Also, you probably need to escape the pipe symbol.

Julian
  • 2,021
  • 16
  • 21
  • I changed my query to grep -E "string1|string2" my.file and that correctly matched the two matches escaping the pipe with -E resulted in no results – rob Oct 24 '11 at 13:44
  • 1
    `grep -E` is equivalent to `egrep`; using `egrep` is probably more idiomatic. In `grep`, `|` is just an ordinary character, and `\|` specifies alternation. In `egrep`, `|` specifies alternation, and `\|` is just the vertical bar character. – Keith Thompson Oct 25 '11 at 00:39
6

The best and most clear way I've found is: grep -e REG1 -e REG2 -e REG3 _FILETOGREP_

I never use pipe as it's less evident and very awkward to get working.

Travis
  • 71
  • 1
  • 1
0

You can find this information by reading the fine manual: grep(1), which you can find by running 'man grep'. It describes the difference between grep and egrep, and basic and regular expressions, along with a lot of other useful information about grep.

Andrew Schulman
  • 3,395
  • 1
  • 21
  • 23
  • 3
    I'm not sure if your desire is to help the OP or to belittle him. In the case that your desire is to help, providing a relevant link and quote from the manual is far more helpful. – Eric Wilson Oct 24 '11 at 20:49
  • My intention is to help the OP by teaching him a life skill: read the manual. It's plain that he didn't do that. Post edited to refer him to grep(1). – Andrew Schulman Oct 24 '11 at 23:37
  • 3
    I'll remove my downvote in response to your edit. I'm fairly certain that this life skill is better learned with explanation and example than by exhortation. – Eric Wilson Oct 25 '11 at 11:25