• Get application security done the right way! Detect, Protect, Monitor, Accelerate, and more…
  • grep, originally developed for Unix-based systems, is one of the most widely used command-line utility in Linux boxes.

    Its name comes from another similar command in ed tool, i.e., g/re/p which stands for globally search for a regular expression and print matching lines. grep basically searches for a given pattern or regular expression from standard input or file and prints the lines that match the given criteria. It’s often used to filter out unnecessary details while printing just the required information from big log files.

    The power of regular expression combines with supported options in grep makes this possible.

    Here we will be covering some of the commonly used grep command in different scenarios by sysadmin or developer.

    So let’s get started…👨‍💻

    grep Command Syntax

    grep command expects a pattern and optional arguments along with a file list if used without piping.

    $ grep [options] pattern [files]

    A simple example is:

    $ grep my file.txt
    my_file
    $

    Searching Multiple Files

    grep enables you to search for the given pattern not just in one but multiple files. Here’s how you can look for a pattern in multiple files by using * wildcard.

    $ sudo grep -i err /var/log/messages*

    Output:

    $ sudo grep err /var/log/messages*
    /var/log/messages:Dec 28 10:36:52 centos7vm kernel: ACPI: Using IOAPIC for interrupt routing
    /var/log/messages:Dec 28 10:36:52 centos7vm kernel: ACPI: PCI Interrupt Link [LNKA] (IRQs 5 9 10 *11)
    /var/log/messages:Dec 28 10:36:52 centos7vm kernel: ACPI: PCI Interrupt Link [LNKB] (IRQs 5 9 *10 11)
    /var/log/messages:Dec 28 10:36:52 centos7vm kernel: ACPI: PCI Interrupt Link [LNKC] (IRQs 5 *9 10 11)
    /var/log/messages:Dec 28 10:36:52 centos7vm kernel: ACPI: PCI Interrupt Link [LNKD] (IRQs 5 9 10 *11)
    /var/log/messages-20201225:Dec 23 23:01:00 centos7vm kernel: ACPI: Using IOAPIC for interrupt routing
    /var/log/messages-20201225:Dec 23 23:01:00 centos7vm kernel: ACPI: PCI Interrupt Link [LNKA] (IRQs 5 9 10 *11)
    /var/log/messages-20201225:Dec 23 23:01:00 centos7vm kernel: ACPI: PCI Interrupt Link [LNKB] (IRQs 5 9 *10 11)
    /var/log/messages-20201225:Dec 23 23:01:00 centos7vm kernel: ACPI: PCI Interrupt Link [LNKC] (IRQs 5 *9 10 11)
    /var/log/messages-20201225:Dec 23 23:01:00 centos7vm kernel: ACPI: PCI Interrupt Link [LNKD] (IRQs 5 9 10 *11)
    /var/log/messages-20201225:Dec 23 23:01:00 centos7vm kernel: BERT: Boot Error Record Table support is disabled. Enable it by using bert_enable as kernel parameter.
    /var/log/messages-20201227:Dec 27 19:11:18 centos7vm kernel: ACPI: PCI Interrupt Link [LNKA] (IRQs 5 9 10 *11)
    /var/log/messages-20201227:Dec 27 19:11:18 centos7vm kernel: ACPI: PCI Interrupt Link [LNKB] (IRQs 5 9 *10 11)
    /var/log/messages-20201227:Dec 27 19:11:18 centos7vm kernel: ACPI: PCI Interrupt Link [LNKC] (IRQs 5 *9 10 11)
    /var/log/messages-20201227:Dec 27 19:11:18 centos7vm kernel: ACPI: PCI Interrupt Link [LNKD] (IRQs 5 9 10 *11)
    /var/log/messages-20201227:Dec 27 19:11:18 centos7vm kernel: BERT: Boot Error Record Table support is disabled. Enable it by using bert_enable as kernel parameter.
    /var/log/messages-20201227:Dec 27 19:11:21 centos7vm kernel: [drm:vmw_host_log [vmwgfx]] *ERROR* Failed to send host log message.
    /var/log/messages-20201227:Dec 27 19:11:21 centos7vm kernel: [drm:vmw_host_log [vmwgfx]] *ERROR* Failed to send host log message.
    $

    You can observe from the above output that the filename is printed first before printing the matching line to indicate where grep found the given pattern.

    Case Insensitive Search

    grep offers to search a pattern without looking at the case of the pattern. Use -i flag to tell grep to ignore case.

    $ grep -i [pattern] [file]

    Output:

    $ grep -i it text_file.txt
    This is a sample text file. It contains
    functionality. You can always use grep with any
    kind of data but it works best with text data.
    It supports numbers like 1, 2, 3 etc. as well as
    This is a sample text file. It's repeated two times.
    $

    Whole Word Search

    It’s not always that we want a partial match but instead expect grep to match a complete word only. You can do that with -w flag.

    $ grep -w [pattern] [file]

    Output:

    $ grep -w is text_file.txt
    This is a sample text file. It contains
    This is a sample text file. It's repeated two times.
    $

    Check Match Count

    Sometimes instead of the actual matched line, we need just the count of successful matches that grep made. We can get this count using -c option.

    $ grep -c [pattern] [file]

    Output:

    $ grep -c is text_file.txt
    2
    $

    Search Sub-directories

    It’s often needed to search files not just in the current working directory but also in subdirectories. grep allows you to easily do that with -r flag.

    $ grep -r [pattern] *

    Output:

    $ grep -r Hello *
    dir1/file1.txt:Hello One
    dir1/file2.txt:Hello Two
    dir1/file3.txt:Hello Three
    $

    As you can observe, grep traverses through each subdirectory inside a current directory and lists the files and lines where a match is found.

    Inverse Search

    If you want to find something which doesn’t match a given pattern, grep allows doing just that with -v flag.

    $ grep -v [pattern] [file]

    Output:

    $ grep This text_file.txt
    This is a sample text file. It contains
    This is a sample text file. It's repeated two times.
    $ grep -v This text_file.txt
    several lines to be used as part of testing grep
    functionality. You can always use grep with any
    kind of data but it works best with text data.
    It supports numbers like 1, 2, 3 etc. as well as
    alphabets and special characters like - + * # etc.
    $

    You can compare the output of grep command on the same pattern and file with and without -v flag. With -v, whichever lines don’t match the pattern gets printed.

    Print Line Numbers

    grep allows you to print line numbers along with printed lines which makes it easy to know where the line is in the file. Use -n option as shown to get line numbers in output.

    $ grep -n [pattern] [file]

    Output:

    $ grep -n This text_file.txt
    1:This is a sample text file. It contains
    7:This is a sample text file. It's repeated two times.
    $

    Limit grep Output

    For big files likes logs etc. grep output can be long and you may just need a fixed number of lines in the output instead of matching everything. We can use –m[num] to limit the printed lines by num. Here’s how to use it:

    $ grep -m[num] [pattern] [file]

    Notice how the use of -m flag affects the output of grep for the same set of conditions in the example below:

    $ grep It text_file.txt
    This is a sample text file. It contains
    It supports numbers like 1, 2, 3 etc. as well as
    This is a sample text file. It's repeated two times.
    $ grep -m2 It text_file.txt
    This is a sample text file. It contains
    It supports numbers like 1, 2, 3 etc. as well as
    $

    Display Additional Lines

    Often we need not just the lines which have a matching pattern but some lines above or below it for better context.

    It is possible to print a line above or below (or both) a line having a pattern using grep by using -A, -B or -C flags with num value. Here num denotes the number of additional lines to be printed which is just above or below the matched line. This is applicable to all matches that grep finds in the specified file or file list.

    $ grep -A[num] [pattern] [file]

    OR

    $ grep -B[num] [pattern] [file]

    OR

    $ grep -C[num] [pattern] [file]

    Below output shows a normal grep output as well as output with flag -A, -B and -C one by one. Notice how grep interprets the flags and their values and the changes in respective output. With -A1 flag, grep prints 1 line which follows just after the matching line.

    Similarly, with -B1 flag, it prints 1 line just before the matching line. With -C1 flag, it prints 1 line which is before and after the matching line.

    $ grep numbers text_file.txt
    It supports numbers like 1, 2, 3 etc. as well as
    $ grep -A1 numbers text_file.txt
    It supports numbers like 1, 2, 3 etc. as well as
    alphabets and special characters like - + * # etc.
    $ grep -B1 numbers text_file.txt
    kind of data but it works best with text data.
    It supports numbers like 1, 2, 3 etc. as well as
    $ grep -C1 numbers text_file.txt
    kind of data but it works best with text data.
    It supports numbers like 1, 2, 3 etc. as well as
    alphabets and special characters like - + * # etc.
    $

    List File Names

    To print just the name of the files where a pattern is found instead of actually matched lines, use -l flag.

    $ grep -l [pattern] [file]

    Here’s an example run:

    $ grep -l su *.txt
    file.txt
    text_file.txt
    $

    Print Exact Lines

    Sometimes we need to print lines that match exactly with a given pattern, not some part of it. grep allows -x flag to do just that.

    $ grep -x [pattern] [file]

    In the below example, file.txt contains a line with just one word “support” and as such gets matched by grep with -x flag while ignoring lines that may contain the words “support” along with other text.

    $ grep -x support *.txt
    file.txt:support
    $ 

    Match Starting String

    Using regular expressions, we can find a string at the start of a line. Here’s how to do it.

    $ grep [options] "^[string]" [file]

    Example:

    $ grep It text_file.txt
    This is a sample text file. It contains
    It supports numbers like 1, 2, 3 etc. as well as
    This is a sample text file. It's repeated two times.
    $ grep ^It text_file.txt
    It supports numbers like 1, 2, 3 etc. as well as
    $

    Observe how using ^ character changes the output. ^ indicates the start of the string and grep matched ^It as any line starting with the word It. Enclosing in quotes can help when the pattern contains spaces etc.

    Match Ending String

    Another common useful regular expression is to match the end of the line pattern.

    $ grep [options] "[string]$" [file]

    Example:

    $ grep "\." text_file.txt
    This is a sample text file. It contains
    functionality. You can always use grep with any
    kind of data but it works best with text data.
    It supports numbers like 1, 2, 3 etc. as well as
    alphabets and special characters like - + * # etc.
    This is a sample text file. It's repeated two times.
    $ grep "\.$" text_file.txt
    kind of data but it works best with text data.
    alphabets and special characters like - + * # etc.
    This is a sample text file. It's repeated two times.
    $

    We tried to match a . character at the end of the line. Since dot (.) is a special meaning character, we need to escape it with \ character. Again notice how output varies when we just match . character and when we use $ to instruct grep to match only such lines which end with . (not the ones that may contain it anywhere in between).

    Use Pattern File

    There may be situations where you have some complex list of patterns that you use often. Instead of writing it down every time, you can specify a list of patterns in a file and use with -f flag. The file should contain one pattern per line.

    $ grep -f [pattern_file] [file_to_match]

    In our example, we’ve created pattern file names pattern.txt with the below contents:

    $ cat pattern.txt
    This
    It
    $

    To use it, use -f flag.

    $ grep -f pattern.txt text_file.txt
    This is a sample text file. It contains
    It supports numbers like 1, 2, 3 etc. as well as
    This is a sample text file. It's repeated two times.
    $
    

    Specify Multiple Patterns

    grep allows specifying multiple patterns using -e flag.

    $ grep -e [pattern1] -e [pattern2] -e [pattern3]...[file]

    Example:

    $ grep -e is -e It -e to text_file.txt
    This is a sample text file. It contains
    several lines to be used as part of testing grep
    It supports numbers like 1, 2, 3 etc. as well as
    This is a sample text file. It's repeated two times.
    $

    Specify Extended RegEx

    grep also supports Extended Regular Expressions or ERE using -E flag. This is similar to egrep command in Linux.

    Using ERE has an advantage when you want to treat meta-characters as is and don’t want to substitute them as strings like grep. This gives you more flexibility in terms of escaping them as we’re required to do in the case of grep. That being said, using -E with grep is equivalent to egrep command.

    $ grep -E '[Extended RegEx]' [file]

    Here’s one use of ERE where we want to print lines that are not commented or blank. This is especially useful for finding something in big configuration files. I’ve additionally used -v flag to NOT print lines matching the pattern '^(#|$)'.

    $ sudo grep -vE '^(#|$)' /etc/ssh/sshd_config
    HostKey /etc/ssh/ssh_host_rsa_key
    HostKey /etc/ssh/ssh_host_ecdsa_key
    HostKey /etc/ssh/ssh_host_ed25519_key
    SyslogFacility AUTHPRIV
    AuthorizedKeysFile      .ssh/authorized_keys
    PasswordAuthentication yes
    ChallengeResponseAuthentication no
    GSSAPIAuthentication yes
    GSSAPICleanupCredentials no
    UsePAM yes
    X11Forwarding yes
    AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
    AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
    AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
    AcceptEnv XMODIFIERS
    Subsystem       sftp    /usr/libexec/openssh/sftp-server
    $

    Conclusion

    The above examples are just the tip of the iceberg. grep supports a range of options and can be a very useful tool in the hand of a person who knows how to effectively use it. We can not only use the examples given above but combine them in different ways to get what we need.

    Refer to its man page to read more about it.

    $ man grep

    Next, learn SFTP command examples.