Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.
grep

Searching for “PATTERNS” or “regex” in grep --help
Release Status Maintained
Last Release 3.12 (2025-04-10)
Language(s) C
Developer(s) GNU grep: GNU Project, et al.
Website https://www.gnu.org/software/grep/

grep (global regular expression print) is a fundamental command-line utility in Unix-like operating systems, designed to “[search] plain-text data sets for lines matching a regular expression[1][2].

History

Developed by Ken Thompson at Bell Labs in 1973 for Unix, grep's creation stemmed from Thompson's need to analyse text in The Federalist Papers for authorship attribution. To handle large files efficiently, he extracted the regex code from the ed text editor into a standalone tool. He named the tool grep because in ed, the command g/re/p prints out all lines that match the pattern re.[2]

Usage

Basic Search

From grep --help:

Usage: grep [OPTION]... PATTERNS [FILE]...
Search for PATTERNS in each FILE.
Example: grep -i 'hello world' menu.h main.c
PATTERNS can contain multiple patterns separated by newlines.

The most basic usage is

cat log.txt | grep "error"

This feeds the content of the log.txt file into grep, which finds all lines with the text “error”. However, grep itself can read files directly, so it is better to just do:

grep "error" log.txt

The most common flags are:

 -i, --ignore-case         ignore case distinctions in patterns and data
 -w, --word-regexp         match only whole words
 -r, --recursive           like --directories=recurse
 -n, --line-number         print line number with output lines

For example,

  • grep -i warning log.txt matches warning, WARNING, Warning, etc.
  • grep -w berry matches berry but not strawberry or blueberry.
  • grep -r admin /etc/ searches for admin in all files inside the /etc/ directory.

Extended Regular Expressions

The -E flag enables extended regular expressions (ERE), while the lack of so only allows basic regular expressions (BRE), a very small subset of what most modern regex implementations provide:[3]

 $ grep --help | grep -- '--' | head -n3  # `--` to tell grep to stop processing flags
  -E, --extended-regexp     PATTERNS are extended regular expressions
  -F, --fixed-strings       PATTERNS are strings
  -G, --basic-regexp        PATTERNS are basic regular expressions

 $ grep --help | grep '^\s+--'

 $ grep --help | grep -E '^\s+--' | head -n3     
      --no-ignore-case      do not ignore case distinctions (default)
      --help                display this help text and exit
      --line-buffered       flush output on every line

Examples

Finding Python Function Calls

In a Python codebase, we can find all calls to functions under the subprocess module with shell=True:

 $ grep -r --include='*.py' -nHE 'subprocess\.\w+\([^)]*shell=True'
./driver.py:69:    return subprocess.call("lspci | grep -q -i NVIDIA", shell=True) == 0
./driver.py:202:    return subprocess.call("lspci | grep -q -i Network | grep -q -i Broadcom", shell=True) == 0
./driver.py:211:    return subprocess.call("lspci | grep -q -i Bluetooth | grep -q -i Broadcom", shell=True) == 0
./util.py:38:        proc = subprocess.Popen(f"chroot {chroot} /tmp/stellar-payload.sh", shell=True)
./util.py:63:        # proc = subprocess.Popen(payload, shell=True)
./util.py:66:        proc = subprocess.Popen(f"pkexec {tmpfile}", shell=True)

(This is run on the Ultramarine stellar codebase)

We can breakdown the flags used in this example:

  • -r: find files recursively (by default in the current working directory)
  • --include='*.py': only examine Python files
  • -n: show line numbers
  • -H: show file name
  • -E: enable ERE

We can divide the pattern subprocess\.\w+\([^)]*shell=True into many parts:

  1. subprocess matches the string “subprocess” literally;
  2. \. matches the full stop literally;
  3. \w+ matches word characters one or more times, where a word character (\w) is any letter, digit or underscore[4];
  4. \( matches for an open parenthesis ( literally;
  5. [^)]* is an inverse character group and matches any characters that are not the closing parenthesis ) zero or more times; and
  6. shell=True matches the string “shell=True” literally.

Finding Code Files with TODOs and FIXMEs

We can list out code files that contains both the word “FIXME” and “TODO”. For a Rust project:

 $ grep -rlZ 'FIXME' --include='*.rs' . | xargs -0 grep -l 'TODO'
./src/pages/_15_installing.rs
./src/main.rs

Flags:

  • -r: find files recursively (by default in the current working directory)
  • -l: output matching files' names only
  • -Z: instead of a new line character, print out a null character after each filename
  • --include='*.rs': only examine Rust files

In this example, the first command outputs the filenames with null separates, then xargs is used to feed the filenames into the second grep command, which searches for “TODO”s in those files.

Extracting All Unique Public IPv4 Addresses from Log Files

We can extract all the unique IPv4 addresses from a directory of log files, but exclude any private IP addresses, such as 10.x.x.x / 192.168.x.x:

grep -rhoE '([0-9]{1,3}\.){3}[0-9]{1,3}' /path/to/logs | sort -u | grep -vE '^10\.|^192\.168\.'

Flags:

  • -r: find files recursively
  • -h: suppress printing of filenames
  • -o: show only matching part of line
  • -E: enable ERE
  • -v: select non-matching lines

For the first pattern:

  1. [0-9] matches the digits (0 to 9 on the ASCII table includes all digits), and {1,3} specifies the length must be between 1 and 3; and
  2. ([0-9]{1,3}\.){3} matches exactly 3 times the above followed by a full stop.

For the second pattern:

  1. ^10\. matches for lines starting with 10.;
  2. ^192\.168\. matches for lines starting with 192.168.; and
  3. | (which indicates “or”) allows matching for the regex specified on the left or the right.

Due to the invert flag (-v), if a line matches the second pattern, it is excluded, and other lines are printed instead.

Alternatives

Faster implementations of grep such as ripgrep (rg) and hypergrep (hgrep) are usually available in mainstream package repositories, but are not bug-for-bug compatible with GNU grep, and usually not pre-installed on most distributions.

The agrep tool (approximate grep) can find matches even if the pattern is not matched exactly[5].

See Also

References

  1. Wikipedia Snapshot for grep, knot.math.usf.edu, 2012 (Accessed 2025-06-21)
  2. 2.0 2.1 grep, Wikipedia, 2025 (Accessed 2025-06-21)
  3. GNU Grep 3.12, gnu.org, 2025 (Accessed: 2025-06-21)
  4. Understanding \w and Its Counterpart \W in Regex, RegexRoo.com, 2025 (Accessed: 2025-06-21)
  5. agrep, Wikipedia, 2025 (Accessed: 2025-06-21)