DEV Community

Cover image for Demystifying GREP
Antonin J. (they/them)
Antonin J. (they/them)

Posted on • Edited on • Originally published at antjanus.com

Demystifying GREP

πŸ“ƒ Cheatsheet

Search for a keyword in a file:

grep keyword file.txt
Enter fullscreen mode Exit fullscreen mode

Search using a regular expression:

grep -E 'regex' file.txt
Enter fullscreen mode Exit fullscreen mode

Search for a keyword in a directory:

grep -r keyword ./directory/path
Enter fullscreen mode Exit fullscreen mode

Combine multiple flags/options to search through a directory, display line numbers, and use regex:

grep -Enr 'regex' ./directory/path
Enter fullscreen mode Exit fullscreen mode

πŸ”Ž What is grep?

Grep is a CLI utility for plain text searches with regex (regular expressions). It's like a Ctrl/Command + F but through a bunch of files and in the command line.

It's another one of those ancient utilities that have proliferated through all Linux and Unixy distributions. Similar to Rsync and tar that I've talked about in the past.

Fortunately, unlike rsync or tar, grep requires a lot less flags and knowledge of the tool to be very productive with it.

Note: Are you on Windows? Check out my article on "how to 'grep' in Powershell"

πŸ“„ Searching for a keyword in a file

If you're in the command line and you don't necessarily want to open a file, or you're dealing with an enormous file, it can be very handy to look for just one line of text using grep.

grep searchkeyword file.txt
Enter fullscreen mode Exit fullscreen mode

Grep will return all the lines containing the text. Depending on your grep variant, you might get line numbers, the keyword highlighted, and other fun information.

πŸ”¬ Searching using regular expressions with the -E flag

Need to use a regular expression because you're a pro at those? Wrapping a regex in quotes will do it most of the time; however, some syntax isn't supported this way so you have to use the -E flag. For example:

grep '^2020-0[0-4]' file.txt
Enter fullscreen mode Exit fullscreen mode

This will work just fine, the [] syntax is supported in basic regex mode; however, specifying occurrences with {} won't work so I recommend defaulting to the -E flag for any regex so you can do neat stuff like this:

grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2}' logfile.txt
Enter fullscreen mode Exit fullscreen mode

This regex will fail in basic mode but the extended mode will match any yyyy-mm-dd date anywhere within your text.

πŸ“‚ Searching through multiple files/directory

Grep lets you also recursively search through many files and directories.

grep -r searchkeyword directoryName
Enter fullscreen mode Exit fullscreen mode

Grep will return all of the matching lines and tell you in which files they were.

🏁 More flags

Grep has a great deal of options. Their manual page is very long and I suggest giving it a look when you feel like grep's basic capabilities just aren't enough for you.

Here's the syntax to add or combine flags when using grep:

grep -flags searchkeyword directoryOrFilename
grep -ir antonin ./documents
Enter fullscreen mode Exit fullscreen mode

In the example, -ir combines both the i and the r flag. Similarly, -Er would let us recursively search with extended regex.

Quick run down of some of these useful flags:

  • i - case insensitive flag
  • n - show line numbers in the matches
  • o - print only the matches, and not the lines (particularly useful with regex)

Top comments (6)

Collapse
 
voyeg3r profile image
SΓ©rgio AraΓΊjo • Edited

We can also use some advanced regex like in this example

any word preceded by big

grep -P '(?<=big)\s\w+' <<-EOF
big house
small house
big car
small car
EOF

outputs each line that NOT starts with big

grep -P '(?<!big)\s\w+' <<-EOF
big house
small house
big car
small car
EOF

The grep below will catch only lines that start with any word but not followed
by house

grep -P '\w+ (?!house)' <<-EOF
big house
small house
big car
small car
EOF

Now any word followed by house

grep -P '\w+ (?=house)' <<-EOF
big house
small house
big car
small car
EOF

The final example:

I had an html file with some wallpapers "name" on it, and I wanted to print just the names without full path

grep -Poh '(?<=href="/pt-br/wallpapers/details/)[^/]*' file-1.html

-P ...................... Perl regex
-o ...................... only the match
-h ...................... omit the filename
(?<=pattern) .... look behind
[^/]* ................... any character but slash

And an ASCII table about some of these regex patterns

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ Lookaround  β”‚ Name                 β”‚ What it Does                   β”‚
    β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚ (?=foo)     β”‚ Lookahead            β”‚ word that follows is foo       β”‚
    β”‚ (?<=foo)    β”‚ Lookbehind           β”‚ preceding word is foo          β”‚
    β”‚ (?!foo)     β”‚ Negative Lookahead   β”‚ word that follows is NOT foo   β”‚
    β”‚ (?<!foo)    β”‚ Negative Lookbehind  β”‚ word behind is NOT foo         β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Collapse
 
slavius profile image
Slavius

Are we talking about GNU grep or BSD grep? It is worth noting as they differ in many places. On all GNU Linux distros you get GNU grep by default, while on OpenBSD, FreeBSD, NetBSD and Mac OS you get BSD grep...

Collapse
 
antjanus profile image
Antonin J. (they/them) • Edited

Good question! I'm using GNU grep on my machine but after consulting the documentation for BSD grep, I verified that everything mentioned on this page should work identically.

Collapse
 
meaculpa profile image
Dom Culpa • Edited

Thank you! Maybe you could add that grep can also be piped to bash for filtering the terminal output. Most of the time I use it this way.

$ command | grep keyword

Collapse
 
antjanus profile image
Antonin J. (they/them)

Will do!

Collapse
 
madebygps profile image
Gwyneth PeΓ±a-Siguenza

Just what I needed. Thanks for sharing.