In this article, we will be learning how to use the grep command from within the Linux terminal.
In my previous article, I had explained How to use find command in Linux and I would request you to read that guide.
So grep stands for Global Regular Expression Print and it allows us to search for some text within files on our system and this is something that you will find yourself using all the time once you become comfortable with it.
Table of Contents
Key features of grep command:
- Search for Single or Multiple patterns
- Search for text in multiple files at once
- Force pattern to match only whole words
- Display non-matching lines(Invert Match)
- Ignore case distinctions
- Print number of lines before and after the match
- Recursive Search
- Display only names of files with matches
- Display only a count of selected lines per file
- Filter Linux command output
- GNU grep supports Regular Expressions
- Display line number with output lines
First of all, let’s focus on some of the most important options that we can use with the grep
.
Options | Explanation |
---|---|
-P, --perl-regexp | Pattern is a Perl regular expression |
-i, --ignore-case | Ignore case distinctions |
-w, --word-regexp | Force Pattern to match only whole words |
-x, --line-regexp | Force Pattern to match only whole lines |
-n, --line-number | Print line number with output lines |
-o, --only-matching | Show only the part of a line matching Pattern |
-r, --recursive | Recursive search |
-R, --dereference-recursive | Follow all symlinks |
-l, --files-with-matches | Print only names of files with selected lines |
-c, --count | Print only a count of selected lines per File |
-B, --before-context | Print number of lines before the match |
-A, --after-context | Print number of lines after the match |
-C, --context | Print number of lines before and after the match |
-V, --version | Check the GNU grep version |
--help | Help/Manual page access |
So, let’s go ahead and look at some practical examples where you might use this.
You must follow the syntax given below to use the grep command.
grep [OPTION]... PATTERN [FILE]...
1. How to search file in Linux using the grep command
First of all, the most basic example is simply searching for some text within a normal file.
I am here in my terminal and in my current directory, there is a file named file.txt that has a bunch of random names and dummy data.
So let’s search this file using grep
to see if it contains the text, Andrew.
If I run that then you can see it didn’t find any results. When there are no results it just jumps to the next line.
$ grep "Andrew" file.txt
helpdesk@ubuntu:~/data$
Instead, let’s search for john and see if that has any results.
$ grep "John" file.txt
John Abraham
Johnny Depp
And we can see that we got two results here where it found two lines containing john and return those entire lines.
Now the second line was johnny depp but it still found within this name.
So, it returned that anyway.
2. Search multiple Patterns using grep
You can search multiple patterns simultaneously.
Let’s take an example.
The following command will search these three patterns: linux, depp and, sahu.
$ grep -i 'linux\|depp\|sahu' file.txt
Balamukunda Sahu
Ayush Sahu
Balamukunda Sahu
Linux Administrator
Linux Operating System
Johnny Depp
johnny depp
3. Force Pattern to match only whole words
So now let’s say that we only wanted it to return a match if it was the whole word.
We only wanted to search for John and not return like Johnny depp.
So, to do this we can use the -w
option.
$ grep -w "John" file.txt
John Abraham
As you can see that it didn’t return Johnny Depp. It only returned the John Abraham.
Because we put in that we only wanted whole words.
4. Ignore case distinctions
Now I also added a lower-case version of that name in that file but it’s currently not returning that because grep is case sensitive.
So we can tell it to not be case sensitive by using the -i
option.
$ grep -wi "john" file.txt
John Abraham
john abraham
As you can see that now we get the lowercase version of that match and the regular case version of that match as well.
5. Print line number with output lines
Now just finding those matches doesn’t give us information other than knowing our text is actually there but sometimes you want some additional information.
For example, it’s common to want to know the line number of where it found our match, and to do this we can add the -n
option to our search.
$ grep -win "john" file.txt
1:John Abraham
3:john abraham
As you can see that now we’re getting some information about these matches.
It found a lowercase version on line 3 of that file and an uppercase version on line 1 of that file.
6. Print the number of lines before our match
Now another common bit of information that you might want is some additional context of where this match is found.
So we might want to also see a certain number of lines before and after the match to get an idea of the context of where this match was found.
And this is especially common if you’re searching for something in a computer program that you wrote and want to see the surrounding code of the match and there are several ways that we can do this.
So, if we want to see a certain number of lines that come before our match then we can use the uppercase -B
option.
So I’m going to go ahead and pull up the last command that we just ran and now we want to add in this Uppercase -B
option.
I’m doing this separate from the other options that we added in because we want to pass in an argument to this.
So, let’s just pass in a 3 which we’ll say that we want to see 3 lines before our match.
$ grep -w -B 3 "Johnny Depp" file.txt
Balamukunda Sahu - Linux Administrator
Simanchal Patra
John Abraham
Johnny Depp
As you can see we got our match but now there’s some additional context here.
So we have 3 lines before our match here.
7. Print the number of lines after our match
Now if we want to see a certain number of lines after our match then we can use the Uppercase -A
option.
$ grep -w -A 3 "Johnny Depp" file.txt
Johnny Depp
john abraham
johnny depp
Shrikant Sahu
We can see that now instead of getting the lines before our match now we’re getting 3 lines after our match.
8. Print the number of lines before and after our match
And if you want to see the lines before and after your match then you can use the Uppercase -C
option. This is also the one that I use most often as well.
$ grep -w -C 3 "Johnny Depp" file.txt
Balamukunda Sahu - Linux Administrator
Simanchal Patra
John Abraham
Johnny Depp
john abraham
johnny depp
Shrikant Sahu
We can see that we got our match and there are 3 lines before the match and 3 lines after the match.
So, like I said I especially use this if I’m searching for some text in a computer program or a function or something that I want to see the context surrounding that match.
9. Search for text in multiple files at once
Okay so that is useful for finding texts in a certain file but what if we wanted to search for text in multiple files at once.
So, let’s say that we wanted to run the same search that we’ve been doing but against every file in our current directory.
Now you might think that we can just do something like this where instead of searching in a specific file that we could just pass in at the current directory as where we want to search.
But if we run that then we can see that we get this error that this our current directory is a directory.
$ grep -wi "linux" ./
grep: ./: Is a directory
So, what we need to do is use an asterisk(*
) wildcard to say that we want everything in this directory.
So if I rerun that same command but put an asterisk(*
) there and run that then we can see that this worked.
$ grep -wi "linux" ./*
./file2.txt:linux
./file2.txt:linux.com
./file2.txt:linux operating system
./file.txt:Balamukunda Sahu - Linux Administrator
grep: ./myfiles: Is a directory
You can see that it also tried to search in this subdirectory that we have in our current folder here.
So it couldn’t search that and we got an error there.
So maybe a better search for us there would be to just search all of the text files and we could do that by running the same command and instead just adding .txt
after that wildcard.
$ grep -wi "linux" ./*.txt
./file2.txt:linux
./file2.txt:linux.com
./file2.txt:linux operating system
./file.txt:Balamukunda Sahu - Linux Administrator
If we run that then we can see that we got all of our matches but that it didn’t try to search this subdirectory here.
10. Recursive search using grep command
Okay, but maybe we wanted it to actually search that subdirectory and this is very common when working on large projects.
Maybe you have a lot of files and subdirectories and are searching for something that you can’t remember exactly what directory or file where it’s located.
So, in that case, you’d just want to search every single file and subdirectory in your project, and to do this we can use a recursive search with the -r
option, and using a recursive search we actually can specify a directory as the starting point.
Let’s do a recursive search for our text within the current directory.
$ grep -wir "linux" ./
./file.txt:Balamukunda Sahu - Linux Administrator
./myfiles/content.txt:Balamukunda Sahu - Linux Administrator
./file2.txt:linux
./file2.txt:linux.com
./file2.txt:linux operating system
As you can see that we got those same results from within our current directory but it also searched the subdirectory and found some matches in this content.txt file.
Instead of that ./
you can just mention the .
to get the same result.
$ grep -wir "linux" .
./file.txt:Balamukunda Sahu - Linux Administrator
./myfiles/content.txt:Balamukunda Sahu - Linux Administrator
./file2.txt:linux
./file2.txt:linux.com
./file2.txt:linux operating system
Using the -R
option will follow all symbolic links.
$ grep -wirR "linux" ./
./file.txt:Balamukunda Sahu - Linux Administrator
./myfiles/content.txt:Balamukunda Sahu - Linux Administrator
./file2.txt:linux
./file2.txt:linux.com
./file2.txt:linux operating system
./backup:Balamukunda Sahu - Linux Administrator
Okay, so that’s nice that we were also able to search subdirectories and get the matches within there as well.
But you do want to be careful with recursive searches just because if you know if you’re in a big directory that has a ton of subdirectories then it’s going to try to search all of those and can take an extremely long time to return any results and if it takes too long you might just have to kill it.
So just be aware that those recursive searches could be searching through lots and lots of files.
11. Print only names of files with matches
Now if you’re searching through multiple files like this then you might not actually be interested in the matches themselves you might only be interested in seeing what files contain a match.
And if you only wanted that information then you can add on the -l
option and only return the files with matches.
$ grep -wirl "linux" ./
./file.txt
./myfiles/content.txt
./file2.txt
As you can see that it doesn’t display the match it just comes up and says that we found a match in file.txt, file2.txt and all the matches within that subdirectory.
12. Print only a count of selected lines per file
Now if we wanted to see how many matches are in each file then we can use the -c
option.
So, if we pull back up the command that we just ran and instead replace that -l
with a -c
.
$ grep -wirc "linux" ./
./file.txt:1
./myfiles/content.txt:1
./file2.txt:3
We can see that we get some similar output as the -l
option but it also displays the number of matches in each file.
13. Filtering Linux command output using grep
Okay, so now let’s look at one practical use case for using grep that we haven’t covered yet.
We can pipe the output of other commands into grep
to search for certain things.
For example, let’s say that we wanted to search our history for our latest sudo.
If we just display our history then we can see that if we wanted to find our sudo then there’s a lot of information here to shift through.
$ history | more
288 tar -xvf myfiles.tar
289 ls
290 rm fi*
291 ls
292 tar -xvf myfiles.tar fi*
293 tar -xvf myfiles.tar --wildcards fi*
294 ls
295 rm fi*
296 ls
--More--
Let’s pipe this in the grep
to narrow it down a bit.
So, we can just run history
as we did before but now we’re going to use a pipe(|
) and pipe that into grep
.
~$ history | grep "sudo"
626 sudo mkdir /division/users
627 sudo mkdir /division
628 sudo mkdir /division/users
629 sudo chmod 777 /division//users/
636 sudo useradd -d /division/users/ user2
641 sudo useradd -u 1100 user4
644 sudo useradd -g 1011 user3
646 sudo useradd -u 1011 -g 1011 user3
647 sudo useradd -u 1005 -g 1005 user3
649 sudo useradd -u 1005 -g 555 user3
653 sudo useradd -g 1002 user3
657 sudo userdel user4
658 sudo userdel user3
663 sudo useradd -u 1003 user3
As you can see that it narrows down our history to lines that match our grep
search and we can even pipe this output into another grep command to narrow it down even further.
I just want to see the sudo
command that I used for the useradd
command then I could run that same last command with another pipe(|
) and another grep
.
So first it’s going to pass the output of history
and narrow those down to the ones that have a “sudo
” and then just going to take this output and pipe(|
) that into grep
again and search for the ones that have a useradd
match.
$ history | grep "sudo" | grep "user3"
644 sudo useradd -g 1011 user3
646 sudo useradd -u 1011 -g 1011 user3
647 sudo useradd -u 1005 -g 1005 user3
649 sudo useradd -u 1005 -g 555 user3
653 sudo useradd -g 1002 user3
658 sudo userdel user3
663 sudo useradd -u 1003 user3
1016 sudo userdel user3
Now we only get our sudo
‘s with the useradd
commands.
Let’s take another example.
The following command will display by searching the user named helpdesk from the /etc/passwd
file.
$ cat /etc/passwd | grep -i helpdesk
helpdesk:x:1000:1000:helpdesk,,,:/home/helpdesk:/bin/bash
14. Regular Expressions in Grep
Let’s see how we can do some more advanced searches using regular expressions.
grep
uses POSIX
regular expressions by default.
Example:1
Let’s say that we wanted to search a file for phone numbers. type the following command to do the same.
$ grep "...-...-...." file.txt
000-000-0000
111-111-1111
222-222-2222
333-333-3333
As you can see that works and we got back the phone numbers from that file.
but let’s say that we wanted to make our search a little bit more specific and instead of searching for any character using the dot we wanted to search specifically for digits using backslash \d
.
if we run this then we don’t get the results that we expect and that’s because grep
isn’t using perl
compatible regular expressions.
$ grep "\d{3}-\d{3}-\d{4}" file.txt
You can get this to work just by passing in the uppercase -P
option here before the search.
$ grep -P "\d{3}-\d{3}-\d{4}" file.txt
000-000-0000
111-111-1111
222-222-2222
333-333-3333
If I wanted to do a more advanced search and see what files contain phone numbers under my current directory then I could do something like this.
Example:2
Use the ^
(caret) symbol to match the expression at the start of a line. In the following example, the string linux will match only if it occurs at the very beginning of a line.
$ grep "^linux" file2.txt
linux
linux.com
linux operating system
Example:3
Use the $
(dollar) symbol to match the expression at the end of a line. In the following example, the string sahu will match only if it occurs at the very end of a line.
$ grep -i "sahu$" file2.txt
Balamukunda Sahu
Ayush Sahu
Shrikant Sahu
Example:4
Use to match any single character enclosed in the brackets. For example, find the lines that contain “accept” or “accent“, you could use the following pattern:
$ grep "acce[np]t" file2.txt
Example:5
Use [^ ]
to match any single character not enclosed in the brackets. The following pattern will match any combination of strings containing co(any_letter_except_l)a, such as coca, cobalt, and so on, but will not match the lines containing cola,
$ grep "co[^l]a" file2.txt
Source: linuxize.com
15. How to select non-matching lines(Invert Match)
To print, non-matching lines use the -v
option with the grep command.
The following command will only display lines that do not contain strings called linux.
$ grep -vi "linux" file.txt
Balamukunda Sahu
Ayush Sahu
Simanchal Patra
John Abraham
Johnny Depp
16. Show only the matched Pattern
The grep command normally prints the entire line of the matched string.
But if you just want to print the matched pattern use the -o
option with the grep
.
$ grep -oi "Sahu" file.txt
Sahu
Sahu
Sahu
Sahu
17. Help/Manual page access
Use the following commands to access the Manual Page/Help Page of grep
command.
$ man grep
$ grep --help
18. Check the GNU grep version
Type the following command to check the GNU grep
version.
$ grep -V
grep (GNU grep) 3.1
You can visit at following websites to get more information on grep.
Conclusion
So that is How to essentially use grep command.
I hope that now you have a good understanding of how the grep command works and you have some ideas for how you can use this within your workflow.
If anyone does have any questions about what we covered in this guide then feel free to ask in the comment section below and I will do my best to answer those.