grep types

This post is 4 years old. (Or older!) Code samples may not work, screenshots may be missing and links could be broken. Although some of the content may be relevant please take it with a pinch of salt.

I was talking to a few of my colleagues today at work and they were not aware that there are different type of grep commands under Linux, such as grep, fgrep, egrep and pgrep, therefore I thought that it would be a nice idea to write this article explaining what each of them does.

grep - even though one may assume that it's just a funny spelling of 'grab' - that is - grab "pattern" from my file - stands for 'Global Regular Expression Print' and it allows you to scan the content of a file - passed in as an argument - and return results that match your pattern. grep accepts lots of parameters and I will mention the few that I use later on.

Let's assume that we have a file that contains the following:

cat test.txt

Auto-creation of a test room that can have one table
Auto-creation of a test table that can have 2 players
Players need to enter their names to join a table
Basic gameplay is fully implemented but additional rules are missing
If the pack of cards get emptied, the discard pile is reshuffled and will become the new pack
Messages are passed in between the connected clients to indicated end of turn events
Enter the gameplay

grep

grep "enter" test.txt
#returns: Players need to enter their names to join a table

Notice that we didn't get the last line as a match because grep does case-sensitive pattern matching by default. One way to get around this is to use the -i flag:

grep -i "enter" test.txt
#returns:
#Players need to enter their names to join a table
#Enter the gameplay

egrep

What if you'd like to search through the file and find the words 'enter' as well as 'gameplay' (an or condition) but you want to do this in one run? This time, you'd have to use egrep - Extended Global Regular Expressions Print - that allows you to add regexes as expressions which also means that while you can simply find special, meta-characters with grep inside your file (such as |, ?, (, ), +), using egrep will transform these into regular expression meta-characters. (If you want to find the pipe symbol in your file for example, you'd have to escape it using backslash: |, otherwise it will be translated as an or operator.

egrep -i "enter|gameplay" test.txt
#returns:
#Players need to enter their names to join a table
#Basic gameplay is fully implemented but additional rules are missing
#Enter the gameplay

(An alternative would be to run grep -E)

pgrep

This particular "grep" is not really comparable to the others as it is looking through running processes to find a process ID of an application (henceforth pgrep stands for Process ID Global Regular Expression Print).

An example usecase would be: pgrep httpd which would return the process ID of the Apache webserver.

fgrep

Last but not least, fgrep, usually referred to as 'fast grep' - officially called as 'Fixed string Global Regular Expression Print' (equivalent of grep -F) does not recognise any regex specific meta-characters, so the search that it executes in the file returns faster. The use-case for fgrep would be in a situation where you are looking for a character in your file - which also happens to be a regex meta-character. For example grep "." test.txt would return every single line from the file, however fgrep "." text.txt would only return the lines where there is an actual dot character.

The two other flags other than -i that I usually use are -aX and -bY - where X and Y are both integers - that allows you to print the X amount of lines after and Y amount of lines before your pattern matched line. For example:

grep "fully" -a1 -b1 test.txt
#returns:
#Players need to enter their names to join a table
#Basic gameplay is fully implemented but additional rules are missing
#Enter the gameplay

The other flag that I also tend to use is -v which emits particular lines from a resultset. Let's assume that every second line in test.txt would be a -1 - maybe another application needs this to add line breaks (I know, it's silly but this is just an assumption for the time being). Therefore, to exclude those from your result you'd do:

grep "fully" test.txt | grep -v "\-1"
#returns:
#Basic gameplay is fully implemented but additional rules are missing

#Don't forget we have -1s all over the place in our test.txt now!

Note that we had to escape the - symbol, otherwise grep would take that as a meta-character and that would fail.