Grep Command in Linux

Updated on

9 min read

Grep Command in Linux

Grep, an acronym for “Global Regular Expression Print”, is one of the most commonly used commands in Linux.

grep is a command-line utility that searches for a specific text string in one or more files. It looks for the pattern in each line of the file and prints out the lines that match it. It is a powerful tool for searching and analyzing large amounts of text data quickly and efficiently. You can use the command to search for specific words, phrases, or regular expressions in files of any size, from small text files to large log files. If no files are specified, grep reads from the standard input, which is usually the output of another command.

This article will demonstrate how to use the grep command with practical examples and detailed explanations of the most common GNU grep options.

grep Command Syntax

The syntax for the grep command is as follows:

grep [OPTIONS] PATTERN [FILE...]

The items in square brackets are optional.

  • OPTIONS - Zero or more options. Grep includes a number of options that control its behavior.
  • PATTERN - Search pattern.
  • FILE - Zero or more input file names.

To be able to search the file, the user running the command must have read access to the file.

Search for a String in Files

The most basic usage of the grep command is to search for a string (text) in a file.

For instance, to find all the lines containing the string “bash” in the /etc/passwd file, you would run the following command:

grep bash /etc/passwd

The output will look something like this:

root:x:0:0:root:/root:/bin/bash
linuxize:x:1000:1000:linuxize:/home/linuxize:/bin/bash

If the string contains spaces, you need to enclose it in single or double quotation marks:

grep "Gnome Display Manager" /etc/passwd

Invert Match (Exclude)

Use the -v ( or --invert-match) option to display the lines that do not match a pattern.

For example, to print the lines that do not contain the string “nologin” you would use:

grep -v nologin /etc/passwd
root:x:0:0:root:/root:/bin/bash
colord:x:124:124::/var/lib/colord:/bin/false
git:x:994:994:git daemon user:/:/usr/bin/git-shell
linuxize:x:1000:1000:linuxize:/home/linuxize:/bin/bash

Using Grep to Filter the Output of a Command

A command’s output can be filtered with grep through piping, and only the lines matching a given pattern will be printed on the terminal. This can make it much easier to find specific information within a large output.

For instance, to find out which processes are running on your system as user www-data you can use the following ps command:

ps -ef | grep www-data
www-data 18247 12675  4 16:00 ?        00:00:00 php-fpm: pool www
root     18272 17714  0 16:00 pts/0    00:00:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn www-data
www-data 31147 12770  0 Oct22 ?        00:05:51 nginx: worker process
www-data 31148 12770  0 Oct22 ?        00:00:00 nginx: cache manager process

You can also chain multiple pipes in on command. As you can see in the output above, there is also a line containing the grep process. If you wish to exclude that line from the output, you can pass it to another grep instance, as demonstrated below:

ps -ef | grep www-data | grep -v grep
www-data 18247 12675  4 16:00 ?        00:00:00 php-fpm: pool www
www-data 31147 12770  0 Oct22 ?        00:05:51 nginx: worker process
www-data 31148 12770  0 Oct22 ?        00:00:00 nginx: cache manager process

To recursively search for a pattern, invoke grep with the -r option (or --recursive). When this option is used, grep will search through all files in the specified directory, including its subdirectories, skipping the symlinks that are encountered recursively. This allows you to easily search through your entire directory structure to find exactly what you’re looking for.

To follow all symbolic links instead of -r, use the -R option (or --dereference-recursive).

Here is an example showing how to search for the string linuxize.com in all files inside the /etc directory:

grep -r linuxize.com /etc

The output will include matching lines prefixed by the full path to the file:

/etc/hosts:127.0.0.1 node2.linuxize.com
/etc/nginx/sites-available/linuxize.com:    server_name linuxize.com   www.linuxize.com;

If you use the -R option, grep will follow all symbolic links:

grep -R linuxize.com /etc

Notice the last line of the output below. That line is not printed when grep is invoked with -r because files inside the Nginx’s sites-enabled directory are symlinks to configuration files inside the sites-available directory.

/etc/hosts:127.0.0.1 node2.linuxize.com
/etc/nginx/sites-available/linuxize.com:    server_name linuxize.com   www.linuxize.com;
/etc/nginx/sites-enabled/linuxize.com:    server_name linuxize.com   www.linuxize.com;

Show Only the Filename

To suppress the default grep output and print only the names of files containing the matched pattern, use the -l ( or --files-with-matches) option.

The following command will search for all files ending with .conf in the current working directory and display only the names of the files containing the string linuxize.com:

grep -l linuxize.com *.conf

The output will look something like this:

tmux.conf
haproxy.conf

The -l flag is commonly used together with the recursive option -R:

grep -Rl linuxize.com /tmp

By default, grep is case-sensitive, meaning the uppercase and lowercase characters are treated as distinct. For example, searching for “linux” will not match “Linux”.

To ignore the case when searching, invoke grep with the -i option (or --ignore-case).

For example, when searching for Zebra without any option, the following command will not show any output i.e, there are matching lines:

grep Zebra /usr/share/words

But if you perform a case insensitive search using the -i option, it will match both upper and lower case letters:

grep -i Zebra /usr/share/words

In the command above “Zebra” will match “zebra”, “ZEbrA” or any other combination of upper and lower case letters for that string.

zebra
zebra's
zebras

Search for Full Words

When searching for a string, grep will display all lines where the string is embedded in larger strings.

For example, if you search for the string “gnu”, grep will match all the lines that contain “gnu” as a standalone string or as part of a larger word such as “cygnus” or “magnum”.

grep gnu /usr/share/words
cygnus
gnu
interregnum
lgnu9d
lignum
magnum
magnuson
sphagnum
wingnut

To return only those lines where the specified string is a whole word (enclosed by non-word characters), use the -w ( or --word-regexp) option.

Word characters include alphanumeric characters (a-z, A-Z, and 0-9) and underscores (_). All other characters are considered as non-word characters.

If you run the command with the -w option, the grep command will return only those lines where gnu is included as a separate word.

grep -w gnu /usr/share/words
gnu

Show Line Numbers

The -n ( or --line-number) option tells grep to display the line number of all the lines that match a given pattern. When this option is used, grep outputs the matched lines to the standard output with their corresponding line numbers as a prefix.

For instance, to display the lines from the /etc/services file containing the string bash prefixed with the matching line number, you can use the following command:

grep -n 10000 /etc/services

The output below shows us that the matches are found on lines 10423 and 10424.

10423:ndmp            10000/tcp
10424:ndmp            10000/udp

Count Matches

To print a count of matching lines to standard output, use the -c ( or --count) option.

In the example below, we are counting the number of accounts that have /usr/bin/zsh as a shell.

regular expressiongrep -c '/usr/bin/zsh' /etc/passwd
4

Quiet Mode

The -q (or --quiet) tells grep to run in quiet mode and not to display anything on the standard output. If a match is found, the command exits with status 0. This is useful when using grep in shell scripts where you want to check whether a file contains a string and perform a specific action depending on the result.

Here is an example of using grep in a quiet mode as a test command in an if statement :

if grep -q PATTERN filename
then
    echo pattern found
else
    echo pattern not found
fi

Basic Regular Expression

GNU Grep has three regular expression feature sets: Basic, Extended, and Perl-compatible.

By default, grep interprets the pattern as a basic regular expression where all characters except the meta-characters are actually regular expressions that match themselves.

Below is a list of most commonly used meta-characters:

  • Use the ^ (caret) symbol to match the expression at the start of a line. In the following example, the string kangaroo will only match if it occurs at the beginning of a line.

    grep "^kangaroo" file.txt
  • Use the $ (dollar) symbol to match the expression at the end of a line. In the following example, the string kangaroo will only match if it occurs at the end of a line.

    grep "kangaroo$" file.txt
  • Use the . (period) symbol to match any single character. For example, to match anything that begins with kan, then has two characters, and ends with the string roo, you could use the following pattern:

    grep "kan..roo" file.txt
  • Use [ ] (brackets) to match any single character enclosed in the brackets. For instance, to find the lines that contain accept or “accent, you could use the following pattern:

    grep "acce[np]t" file.txt
  • 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" file.txt

To escape the special meaning of the next character, use the \ (backslash) symbol.

Extended Regular Expressions

To interpret the pattern as an extended regular expression, use the -E ( or --extended-regexp) option. Extended regular expressions include all of the basic meta-characters, along with additional meta-characters to create more complex and powerful search patterns. Below are some examples:

  • Match and extract all email addresses from a given file:

    grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" file.txt
  • Match and extract all valid IP addresses from a given file:

    grep -E -o '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' file.txt

The -o option is used to print only the matching string.

Search for Multiple Strings (Patterns)

Two or more search patterns can be joined using the OR operator |.

By default, grep interprets the pattern as a basic regular expression where the meta-characters such as | lose their special meaning, and their backslashed versions must be used.

In the example below, we are searching all occurrences of the words fatal, error, and critical in the Nginx log error file:

grep 'fatal\|error\|critical' /var/log/nginx/error.log

If you use the extended regular expression option -E, then the operator | should not be escaped, as shown below:

grep -E 'fatal|error|critical' /var/log/nginx/error.log

To print a specific number of lines before matching lines, use the -B ( or --before-context) option.

For example, to display five lines of leading context before matching lines, you would use the following command:

grep -B 5 root /etc/passwd

To print a specific number of lines after matching lines, use the -A ( or --after-context) option.

For example, to display five lines of trailing context after matching lines, you would use the following command:

grep -A 5 root /etc/passwd

Conclusion

The grep command allows you to search for a pattern inside of files. If a match is found, grep prints the lines containing the specified pattern.

There’s much more to learn about Grep on Grep User’s Manual page.

If you have any questions or feedback, feel free to leave a comment.