This basic command it’s one of the most used when working with a Linux shell which brings a lot of powerful options to search text like the use of regular expressions. So in this post, it will be explained how to use the grep
Linux command through some use cases.
The grep command syntax
The syntax of the grep
command is:
grep [OPTION]… PATTERN [FILE]…
As other Linux commands, it has multiple options to leverage the output of grep
and most of them can be combined to obtain a more refined results. These are the options that this post will explain in more detail:
-i : ignore case distinctions
–e : use PATTERN for matching
–v : select non-matching lines
-w : force PATTERN to match only whole words
-A : print NUM lines of trailing context
-B : print NUM lines of leading context
-r : search PATTERN in subdirectories recursively also
-l : print only names of FILEs containing matches
Case sensitive pattern or text search
If grep
is run without any options but with a pattern and a target file, it will get all the lines that contains the pattern passed to the command.
$ grep off text
coffeemaker
takeoff
This pattern search without any option is case sensitive, se keep in mind this when using the command in this way.
Ignore case pattern or text search
To perform the same pattern search without case sensitive, the “-i” option can be used:
$ grep oFf text
$ grep -i oFf text
coffeemaker
takeoff
The example above shows the execution of grep with and without the “-i” option to ignore case distinctions and the second grep
will show results despite that the “F” character doesn’t match in the word found. This means that the command with “-i” option, the pattern could be “OFF”, “Off”, “OfF” and so on but the results will be the same.
Multiple pattern search
With grep command, it is possible to search multiple patterns so either one or another will be a match and showed as a result. In order to do it, the option to use is “-e”:
$ grep -e off -e sand text
coffeemaker
sandlot
takeoff
The above command with multiple pattern search can be combined with the “-i” option so the following command line will throw the same results as the above one:
$ grep -i -e OFf -e Sand text
Invert match pattern search or select lines that don’t match the pattern
There’s an option to run grep to get all the lines that doesn’t match a pattern by using the the “-v” option:
$ grep -v off text
if you combine with the multiple pattern match with “-e”, you can refine further the text search by getting all the lines from the text that don’t have any of the patterns passed:
$ grep -v -e off -e day -e and text
Again, you can combine the previous example with the “-i” option, to do the same negative matching ignoring case.
Exact pattern match search
Another useful grep
option is the “-w” which will change the command to do an exact match. These means that the word matched must have exactly the same characters to be considered as a match for the command:
$ grep -w off text
$ grep -w coffee text
$ grep -w coffeemaker text
coffeemaker
The example above, shows that despite “off” and “coffee” is inside the word “coffeemaker” it will not be considered as an exact match so no output is showed by grep
. However, if the whole word is provided like in the third command line, then the match will be printed.
Search with a pattern file list
Typing the multiple patterns to look for in the grep
command may not be very effective so, there’s an option to get a pattern list from a file to search it in a text. The option related is the “-f”:
$ cat patterns
life
off
sand
good vibes
$ grep -f patterns text
lifework
coffeemaker
lifeblood
lifeguard
sandlot
takeoff
Each line from the pattern file will be considered as a single pattern input to the grep command, so the example above will be similar to the next command line:
$ grep -e life -e off -e sand -e "good vibes" text
Search lines that only matches 2 or multiple patterns
Another useful usage to be considered is to combine grep
commands to get the lines that match more than one pattern. This is different from using the “-e” option to seek multiple patterns, which will get any line that matches any of pattern. Here’s how you can do it:
$ grep off text
coffeemaker
takeoff
$ grep off text | grep maker
coffeemaker
So, as you can see, the first command will get any line with “off” pattern. But if you want to get the line that has “off” but also “maker” then the second command will do the trick.
Get or print the lines after or before a pattern match
Sometimes, to get the whole line when getting a match is not exactly what you want and you are looking for a section of text right next to the match. The option to do it is the “-A”:
$ grep -A 2 off text
coffeemaker
lifeblood
fishbowl
--
takeoff
daydream
jetliner
In the previous example, the grep output will show the next 2 lines as well right after the matching line. This could be useful to get sections of text like the content of a XML tag.
The same can be done but with the previous 2 lines right before the matching line with “-B” option:
$ grep -B 2 off text
lifework
overcoat
coffeemaker
--
pickup
weekday
takeoff
Bear in mind that most of the options commented previously can be combined to get a more refined result, so keep trying combining them until you get the desired results.
Search patterns with regexp
The regular expression is a powerful way to define more complex pattern search and grep
allows such patterns. Here are some examples of grep using regular expressions:
$ grep ".off" text
coffeemaker
takeoff
$ grep "..off" text
takeoff
As you may appreciate, the first regexp grep command will get the lines matching “off” and whatever single character before it (The wildcard “.”). However, the second one will output the lines matching “off” and any 2 characters before the pattern. So, in this second command, “coffeemaker” is not considered since it has only one character before “off” and the regexp pattern needs 2.
The following command line looks for a word that starts with (The “^” symbol) at least one character and followed by the string “off”:
$ grep ^.off text
coffeemaker
And in the next command, it will look for a word ended by sequence “lot” (The “$” symbol), preceded by any 2 characters:
$ grep k.lot$ text
sandlot
In this next example, grep will look for any line starting with lower case “f” followed by any lower case alphabet letter from “a” to “n” and followed by another lower case alphabet letter from “h” to “z”:
$ grep "^f[a-n][h-z]" text
fishbowl
fireworks
fisherman
fishhook
Some of the characters has it’s own way to be declared so, to find out any line recursive
The grep
command by default use the Basic Regular Expressions (BRE) to perform the matches, meaning that it will use the meta characters “.”, “*”, “^”, “$” and “[]” for the regexp.
However, by using the “-E” option, grep
is able to interpret Extended Regular Expression (ERE) to perform an enhanced pattern match and will use meta characters like “()”, “+”, “{}”, “|”, “?”. So it is possible to make the following searches like:
$ grep -E "^.ish|snow" text
fishbowl
snowbird
fisherman
fishhook
dishpan
The above example is looking for lines starting by either any character followed by “ish” or “snow” in the “text” file.
Another example showed next, will get the lines that has the “ir” string at least once:
$ grep -E "ir{1,}" text
snowbird
fireworks
Print the matched line number
You can get the number of the matched line in the text by running:
$ grep -n son text
38:grandson
47:spokesperson
This could be useful to get an idea of where is the patterns located in the text.
Search pattern in multiple files recursively
One of the best options that grep
brings is the “-r” parameter that allows you to search a pattern in multiple files recursively from the path you are running the command.
Let’s say that we have the following files from the current directory:
$ ls -lR
.:
total 8
drwxrwxr-x. 2 fse fse 25 Apr 17 00:43 com
-rw-rw-r--. 1 fse fse 484 Apr 17 00:43 text
-rw-rw-r--. 1 fse fse 14 Apr 17 01:03 text2
./com:
total 4
-rw-rw-r--. 1 fse fse 482 Apr 17 00:43 anothertext
Then, by running grep in the following way, we can search the pattern “fo” in all the files from the current path:
$ grep -r fo *
com/anothertext:forecast
com/anothertext:footlocker
text:tenfold
text:foreknowledge
text:foreshadow
For each mach found in the files, grep
will precede the output with the relative path of the file that the patter was found.
However, the pattern search is not considering the hidden files. To include them in the search, simply skip the file parameter from the command:
$ grep -r fo
.bashrc:# Uncomment the following line if you don't like systemctl's auto-paging feature:
text:tenfold
text:foreknowledge
text:foreshadow
com/anothertext:forecast
com/anothertext:footlocker
.viminfo:# This viminfo file was generated by Vim 7.4.
This is a pretty useful option from grep
for debugging purposes or searching any particular information. It is also possible to combine “-r” with other options described above so the recursive pattern search could be done with a regular expression:
$ grep -r .hou
text:courthouse
com/anothertext:longhouse
If you want to limit the search to all the files from the current path only, then omit the “-r” option and place only a wildcard “*” at the end of the command:
$ grep .bow *
grep: com: Is a directory
text:fishbowl
text2:elbow
text2:rainbow
Get the file name or file path that match the pattern
Sometimes the “-r” option could flood the output with all the matches it finds, making it hard to check which is the file that has a match with the pattern. So, in order to obtain only the file that make the match, the option “-l” could be helpful to obtain only the files that contains the pattern. Here are some examples:
$ grep -rl .bow *
text
text2
$ grep -rl .in *
com/anothertext
text
text2
Match with grep the symbols like dot or wildcard and avoid them interpreted as regular expression
The grep command will work by default with regular expressions and if you try to search the symbols like “.”, “*” or “[” that are interpreted as part of the regexp, the escape character “\” should precede the symbol and the pattern surrounded by double or single quotes. Here are some examples:
$ grep -r "\."
.bash_logout:# ~/.bash_logout
.bash_profile:# .bash_profile
.bash_profile:if [ -f ~/.bashrc ]; then
.bash_profile: . ~/.bashrc
.bash_profile:PATH=$PATH:$HOME/.local/bin:$HOME/bin
.bashrc:# .bashrc
.bashrc: . /etc/bashrc
.viminfo:# This viminfo file was generated by Vim 7.4.
.viminfo: . 2 6
.viminfo: . 50 0
.viminfo: . 50 0
$ grep -r "\*"
.viminfo:*encoding=utf-8
$ grep -r "\["
.bash_profile:if [ -f ~/.bashrc ]; then
.bashrc:if [ -f /etc/bashrc ]; then
$ grep -r "\.bashrc \]"
.bash_profile:if [ -f ~/.bashrc ]; then
Location or full path of grep
The grep
command is normally located in /usr/bin/grep
:
$ which grep
alias grep='grep --color=auto'
/usr/bin/grep