The grep
command is one of the most useful commands in a Linux terminal environment. The name grep
stands for “global regular expression print”. This means that you can use grep
to check whether the input it receives matches a specified pattern. This seemingly trivial program is extremely powerful; its ability to filter input based on complex rules makes it a popular link in many command chains.
In this tutorial, we will guide you through using grep
with regular expressions for efficient text searching, starting with the fundamentals and moving toward advanced techniques. We will begin by covering basic literal matching and exploring the most common grep
command-line options to refine your searches. From there, you will learn to construct powerful search patterns, starting with basic regular expressions for fundamental pattern matching. We will then advance to the more flexible extended regular expressions and the feature-rich Perl-Compatible Regular Expressions (PCRE), which enable more complex and precise searches. To solidify your understanding, we will walk through practical, real-world examples and conclude with performance considerations to help you optimize your commands for speed and efficiency.
Key takeaways:
grep
command, which stands for “global regular expression print,” checks whether the input it receives matches a specified pattern.-i
to ignore case, -v
to find lines that do not contain the pattern, and -n
to display the line number of matches.^
for the beginning of a line and $
for the end of a line.[]
) can be used to match any one character from a specified group, while the period (.
) matches any single character.\
).-E
flag or the egrep
command enables extended regular expressions, which include additional meta-characters for alternation (|
) and grouping (()
).-P
flag unlocks Perl Compatible Regular Expressions (PCRE), which support advanced features like lazy matching and lookarounds.zgrep
utility works just like grep
but is used for searching through compressed .gz
files without needing to decompress them first.grep
excels as a high-performance tool for bulk data cleanup and preprocessing.grep
is not well-suited for handling multiline patterns, for which alternative tools like awk
and perl
are more effective.To follow along with this guide, you will need access to a computer running a Linux-based operating system. This can either be a virtual private server which you’ve connected to with SSH or your local machine. Note that this tutorial was validated using a Linux server running Ubuntu 20.04, but the examples given should work on a computer running any version of any Linux distribution.
If you plan to use a remote server to follow this guide, we encourage you to first complete our Initial Server Setup guide. Doing so will set you up with a secure server environment — including a non-root user with sudo
privileges and a firewall configured with UFW — which you can use to build your Linux skills.
In this tutorial, you’ll use grep
to search the GNU General Public License version 3 for various words and phrases.
If you’re on an Ubuntu system, you can find the file in the /usr/share/common-licenses
folder. Copy it to your home directory:
- cp /usr/share/common-licenses/GPL-3 .
If you’re on another system, use the curl
command to download a copy:
- curl -o GPL-3 https://www.gnu.org/licenses/gpl-3.0.txt
You’ll also use the BSD license file in this tutorial. On Linux, you can copy that to your home directory with the following command:
- cp /usr/share/common-licenses/BSD .
If you’re on another system, create the file with the following command:
- cat << 'EOF' > BSD
- Copyright (c) The Regents of the University of California.
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
- EOF
Now that you have the files, you can start working with grep
.
In the most basic form, you use grep
to match literal patterns within a text file. This means that if you pass grep
a word to search for, it will print out every line in the file containing that word.
Execute the following command to use grep
to search for every line that contains the word GNU
:
- grep "GNU" GPL-3
The first argument, GNU
, is the pattern you’re searching for, while the second argument, GPL-3
, is the input file you wish to search.
The resulting output will be every line containing the pattern text:
Output GNU GENERAL PUBLIC LICENSE
The GNU General Public License is a free, copyleft license for
the GNU General Public License is intended to guarantee your freedom to
GNU General Public License for most of our software; it applies also to
Developers that use the GNU GPL protect your rights with two steps:
"This License" refers to version 3 of the GNU General Public License.
13. Use with the GNU Affero General Public License.
under version 3 of the GNU Affero General Public License into a single
...
...
On some systems, the pattern you searched for will be highlighted in the output.
By default, grep
will search for the exact specified pattern within the input file and return the lines it finds. You can make this behavior more useful though by adding some optional flags to grep
.
If you want grep
to ignore the “case” of your search parameter and search for both upper- and lower-case variations, you can specify the -i
or --ignore-case
option.
Search for each instance of the word license
(with upper, lower, or mixed cases) in the same file as before with the following command:
- grep -i "license" GPL-3
The results contain: LICENSE
, license
, and License
:
Output GNU GENERAL PUBLIC LICENSE
of this license document, but changing it is not allowed.
The GNU General Public License is a free, copyleft license for
The licenses for most software and other practical works are designed
the GNU General Public License is intended to guarantee your freedom to
GNU General Public License for most of our software; it applies also to
price. Our General Public Licenses are designed to make sure that you
(1) assert copyright on the software, and (2) offer you this License
"This License" refers to version 3 of the GNU General Public License.
"The Program" refers to any copyrightable work licensed under this
...
...
If there was an instance with LiCeNsE
, that would have been returned as well.
If you want to find all lines that do not contain a specified pattern, you can use the -v
or --invert-match
option.
Search for every line that does not contain the word the
in the BSD license with the following command:
- grep -v "the" BSD
You’ll receive this output:
OutputAll rights reserved.
Redistribution and use in source and binary forms, with or without
are met:
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
...
...
Since you did not specify the “ignore case” option, the last two items were returned as not having the word the
.
It is often useful to know the line number that the matches occur on. You can do this by using the -n
or --line-number
option. Re-run the previous example with this flag added:
- grep -vn "the" BSD
This will return the following text:
Output2:All rights reserved.
3:
4:Redistribution and use in source and binary forms, with or without
6:are met:
13: may be used to endorse or promote products derived from this software
14: without specific prior written permission.
15:
16:THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17:ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
...
...
Now you can reference the line number if you want to make changes to every line that does not contain the
. This is especially handy when working with source code.
In the introduction, you learned that grep
stands for “global regular expression print”. A “regular expression” is a text string that describes a particular search pattern.
Different applications and programming languages implement regular expressions slightly differently. In this tutorial you will only be exploring a small subset of the way that grep
describes its patterns.
In the previous examples in this tutorial, when you searched for the words GNU
and the
, you were actually searching for basic regular expressions which matched the exact string of characters GNU
and the
. Patterns that exactly specify the characters to be matched are called “literals” because they match the pattern literally, character-for-character.
It is helpful to think of these as matching a string of characters rather than matching a word. This will become a more important distinction as you learn more complex patterns.
All alphabetical and numerical characters (as well as certain other characters) are matched literally unless modified by other expression mechanisms.
Anchors are special characters that specify where in the line a match must occur to be valid.
For instance, using anchors, you can specify that you only want to know about the lines that match GNU
at the very beginning of the line. To do this, you could use the ^
anchor before the literal string.
Run the following command to search the GPL-3
file and find lines where GNU
occurs at the very beginning of a line:
- grep "^GNU" GPL-3
This command will return the following two lines:
OutputGNU General Public License for most of our software; it applies also to
GNU General Public License, you may choose any version ever published
Similarly, you use the $
anchor at the end of a pattern to indicate that the match will only be valid if it occurs at the very end of a line.
This command will match every line ending with the word and
in the GPL-3
file:
- grep "and$" GPL-3
You’ll receive this output:
Outputthat there is no warranty for this free software. For both users' and
The precise terms and conditions for copying, distribution and
License. Each licensee is addressed as "you". "Licensees" and
receive it, in any medium, provided that you conspicuously and
alternative is allowed only occasionally and noncommercially, and
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
provisionally, unless and until the copyright holder explicitly and
receives a license from the original licensors, to run, modify and
make, use, sell, offer for sale, import and otherwise run, modify and
The period character (.) is used in regular expressions to mean that any single character can exist at the specified location.
For example, to match anything in the GPL-3
file that has two characters and then the string cept
, you would use the following pattern:
- grep "..cept" GPL-3
This command returns the following output:
Outputuse, which is precisely where it is most unacceptable. Therefore, we
infringement under applicable copyright law, except executing it on a
tells the user that there is no warranty for the work (except to the
License by making exceptions from one or more of its conditions.
form of a separately written license, or stated as exceptions;
You may not propagate or modify a covered work except as expressly
9. Acceptance Not Required for Having Copies.
...
...
This output has instances of both accept
and except
and variations of the two words. The pattern would also have matched z2cept
if that was found as well.
By placing a group of characters within brackets (\[
and \]
), you can specify that the character at that position can be any one character found within the bracket group.
For example, to find the lines that contain too
or two
, you would specify those variations succinctly by using the following pattern:
- grep "t[wo]o" GPL-3
The output shows that both variations exist in the file:
Outputyour programs, too.
freedoms that you received. You must make sure that they, too, receive
Developers that use the GNU GPL protect your rights with two steps:
a computer network, with no transfer of a copy, is not conveying.
System Libraries, or general-purpose tools or generally available free
Corresponding Source from a network server at no charge.
...
...
Bracket notation gives you some interesting options. You can have the pattern match anything except the characters within a bracket by beginning the list of characters within the brackets with a ^
character.
This example is like the pattern .ode
, but will not match the pattern code
:
- grep "[^c]ode" GPL-3
Here’s the output you’ll receive:
Output 1. Source Code.
model, to give anyone who possesses the object code either (1) a
the only significant mode of use of the product.
notice like this when it starts in an interactive mode:
Notice that in the second line returned, there is, in fact, the word code
. This is not a failure of the regular expression or grep. Rather, this line was returned because earlier in the line, the pattern mode
, found within the word model
, was found. The line was returned because there was an instance that matched the pattern.
Another helpful feature of brackets is that you can specify a range of characters instead of individually typing every available character.
This means that if you want to find every line that begins with a capital letter, you can use the following pattern:
- grep "^[A-Z]" GPL-3
Here’s the output this expression returns:
OutputGNU General Public License for most of our software; it applies also to
States should not allow patents to restrict development and use of
License. Each licensee is addressed as "you". "Licensees" and
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
System Libraries, or general-purpose tools or generally available free
Source.
User Product is transferred to the recipient in perpetuity or for a
...
...
Due to some legacy sorting issues, it is often more accurate to use POSIX character classes instead of character ranges like you just used.
To discuss every POSIX character class would be beyond the scope of this guide, but an example that would accomplish the same procedure as the previous example uses the \[:upper:\]
character class within a bracket selector:
- grep "^[[:upper:]]" GPL-3
The output will be the same as before.
Finally, one of the most commonly used meta-characters is the asterisk, or *
, which means “repeat the previous character or expression zero or more times”.
To find each line in the GPL-3
file that contains an opening and closing parenthesis, with only letters and single spaces in between, use the following expression:
- grep "([A-Za-z ]*)" GPL-3
You’ll get the following output:
Output Copyright (C) 2007 Free Software Foundation, Inc.
distribution (with or without modification), making available to the
than the work as a whole, that (a) is included in the normal form of
Component, and (b) serves only to enable use of the work with that
(if any) on which the executable work runs, or a compiler used to
(including a physical distribution medium), accompanied by the
(including a physical distribution medium), accompanied by a
place (gratis or for a charge), and offer equivalent access to the
...
...
So far you’ve used periods, asterisks, and other characters in your expressions, but sometimes you need to search for those characters specifically.
There are times where you’ll need to search for a literal period or a literal opening bracket, especially when working with source code or configuration files. Because these characters have special meaning in regular expressions, you need to “escape” these characters to tell grep
that you do not wish to use their special meaning in this case.
You escape characters by using the backslash character (\
) in front of the character that would normally have a special meaning.
For instance, to find any line that begins with a capital letter and ends with a period, use the following expression which escapes the ending period so that it represents a literal period instead of the usual “any character” meaning:
- grep "^[A-Z].*\.$" GPL-3
This is the output you’ll see:
OutputSource.
License by making exceptions from one or more of its conditions.
License would be to refrain entirely from conveying the Program.
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
SUCH DAMAGES.
Also add information on how to contact you by electronic and paper mail.
Now let’s look at other regular expression options.
The grep
command supports a more extensive regular expression language by using the -E
flag or by calling the egrep
command instead of grep
.
These options open up the capabilities of “extended regular expressions”. Extended regular expressions include all of the basic meta-characters, along with additional meta-characters to express more complex matches.
One of the most useful abilities that extended regular expressions open up is the ability to group expressions together to manipulate or reference as one unit.
To group expressions together, wrap them in parentheses. If you would like to use parentheses without using extended regular expressions, you can escape them with the backslash to enable this functionality. This means that the following three expressions are functionally equivalent:
- grep "\(grouping\)" file.txt
- grep -E "(grouping)" file.txt
- egrep "(grouping)" file.txt
Similar to how bracket expressions can specify different possible choices for single character matches, alternation allows you to specify alternative matches for strings or expression sets.
To indicate alternation, use the pipe character |
. These are often used within parenthetical grouping to specify that one of two or more possibilities should be considered a match.
The following will find either GPL
or General Public License
in the text:
- grep -E "(GPL|General Public License)" GPL-3
The output looks like this:
Output The GNU General Public License is a free, copyleft license for
the GNU General Public License is intended to guarantee your freedom to
GNU General Public License for most of our software; it applies also to
price. Our General Public Licenses are designed to make sure that you
Developers that use the GNU GPL protect your rights with two steps:
For the developers' and authors' protection, the GPL clearly explains
authors' sake, the GPL requires that modified versions be marked as
have designed this version of the GPL to prohibit the practice for those
...
...
Alternation can select between more than two choices by adding additional choices within the selection group separated by additional pipe (|
) characters.
Like the *
meta-character that matched the previous character or character set zero or more times, there are other meta-characters available in extended regular expressions that specify the number of occurrences.
To match a character zero or one times, you can use the ?
character. This makes character or character sets that came before optional, in essence.
The following matches copyright
and right
by putting copy
in an optional group:
- grep -E "(copy)?right" GPL-3
You’ll receive this output:
Output Copyright (C) 2007 Free Software Foundation, Inc.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
"Copyright" also means copyright-like laws that apply to other kinds of
...
The +
character matches an expression one or more times. This is almost like the *
meta-character, but with the +
character, the expression must match at least once.
The following expression matches the string free
plus one or more characters that are not white space characters:
- grep -E "free[^[:space:]]+" GPL-3
You’ll see this output:
Output The GNU General Public License is a free, copyleft license for
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
When we speak of free software, we are referring to freedom, not
have the freedom to distribute copies of free software (and charge for
you modify it: responsibilities to respect the freedom of others.
freedoms that you received. You must make sure that they, too, receive
protecting users' freedom to change the software. The systematic
of the GPL, as needed to protect the freedom of users.
patents cannot be used to render the program non-free.
To specify the number of times that a match is repeated, use the brace characters ({
and }
). These characters let you specify an exact number, a range, or an upper or lower bounds to the amount of times an expression can match.
Use the following expression to find all of the lines in the GPL-3
file that contain triple-vowels:
- grep -E "[AEIOUaeiou]{3}" GPL-3
Each line returned has a word with three vowels:
Outputchanged, so that their problems will not be attributed erroneously to
authors of previous versions.
receive it, in any medium, provided that you conspicuously and
give under the previous paragraph, plus a right to possession of the
covered work so as to satisfy simultaneously your obligations under this
To match any words that have between 16 and 20 characters, use the following expression:
- grep -E "[[:alpha:]]{16,20}" GPL-3
Here’s this command’s output:
Output certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
c) Prohibiting misrepresentation of the origin of that material, or
Only lines containing words within that length are displayed.
While extended regular expressions (-E
) add a lot of power, some systems offer an even more feature-rich engine: Perl Compatible Regular Expressions (PCRE). You can unlock this functionality with the -P
flag. This engine is common in programming languages like Python and JavaScript, and it brings advanced capabilities directly to your command line.
Note: The -P
option is a GNU extension and may not be available on all systems, such as the default version of grep on macOS (which is BSD-based).
Let’s explore two powerful features PCRE enables: lazy matching and lookarounds.
By default, quantifiers like *
and +
are greedy. This means they try to match the longest possible string. For instance, if you have the text <a>test1</a> <a>test2</a>
and you try to match an HTML tag with <.*>
, the pattern will match the entire string from the first <
to the last >
.
Create a file named tags.html
to see this in action:
echo '<a>test1</a> <a>test2</a>' > tags.html
Now, run a greedy search:
grep -P -o "<.*>" tags.html
The -o
flag tells grep to only output the matching part of the line. The result is the entire line, which is often not what you want:
Output<a>test1</a> <a>test2</a>
To solve this, you can make the quantifier lazy by adding a ?
after it. A lazy quantifier matches the shortest possible string.
grep -P -o "<.*?>" tags.html
This correctly identifies each tag as a separate match:
Output<a>
</a>
<a>
</a>
Lazy matching is essential when you’re parsing text with clear start and end delimiters but with variable content in between.
Lookarounds are zero-width assertions. They let you check for the presence of a pattern before (lookbehind) or after (lookahead) your main pattern without including it in the actual match. This is incredibly useful for matching based on context.
?=...
): Asserts that the subpattern ...
must follow the main pattern.?<=...
): Asserts that the subpattern ...
must precede the main pattern.Imagine you want to find every instance of the word “license” in GPL-3
, but only when it is immediately followed by the word “document”.
grep -P -o "license(?= document)" GPL-3
The output will only show the word license
, even though the match depended on the word document
coming after it:
Outputlicense
Similarly, you could use a positive lookbehind to find a number that is preceded by the string "version ".
grep -P -o "(?<=version )[0-9]" GPL-3
This command finds the version number 3
from the phrase “version 3” without including "version " in the output.
Output3
3
3
Lookarounds are a powerful tool for extracting precise information from structured text.
Once you’re comfortable with grep’s core functionality, you can focus on making your searches faster, your scripts more reliable, and your workflow more efficient.
Not all regular expressions are created equal. A poorly written pattern can be dramatically slower than an efficient one, especially on large files.
Regex Efficiency: Be cautious of complex patterns with nested quantifiers and alternation, such as (a|b*)+
. These can lead to a condition known as catastrophic backtracking, where the regex engine’s runtime grows exponentially. When possible, write patterns that are more specific and avoid ambiguity.
Modern Alternatives: For searching large codebases, tools like ripgrep
(rg
) are built for speed. They often outperform grep
by leveraging parallelism and smart defaults, like automatically ignoring files listed in your .gitignore
.
Useful Performance Flags:
--line-buffered
: When grep
is part of a pipeline (e.g., tail -f logfile | grep 'ERROR'
), this flag forces it to process output line-by-line. This is crucial for real-time log monitoring, ensuring you see matches as they happen rather than waiting for an output buffer to fill.--mmap
: On some systems, this option can improve performance by using memory-mapped I/O to read files, which can be faster than standard read operations for very large files.A shell script that works on your Linux machine might fail on a colleague’s Mac. This is often due to differences between GNU grep
(standard on Linux) and BSD grep
(standard on macOS). GNU grep
generally has more features, like the PCRE engine (-P
) and more advanced options. Always test your scripts in different environments if portability is a goal.
For a common sysadmin task, such as searching through compressed log files, you don’t need to decompress them first. The zgrep
utility works just like grep
but on .gz
compressed files.
zgrep "ERROR" /var/log/syslog.2.gz
This command searches for “ERROR” inside the compressed syslog.2.gz
file without creating a temporary uncompressed file.
When building scripts, robustness is key. Filenames with spaces or special characters can break simple pipelines.
Safe Pipelines with --null
: The grep -l
command lists files containing a match. If you pipe this list to another command like xargs
, filenames with spaces will cause errors. To solve this, use the -Z
or --null
option, which separates filenames with a null character instead of a newline. The xargs
command can then read this input using its -0
option.
grep -lZ "pattern" /path/* | xargs -0 rm
This command safely finds all files in /path/
containing “pattern” and deletes them, even if their names contain spaces or other special characters.
Descriptive Input with --label
: When piping input to grep
from another command, the source is typically labeled (standard input
). The --label
flag allows you to assign a more descriptive name, which is useful for creating clearer logs or script outputs.
echo "This is an error" | grep --label="ErrorStream" "error"
OutputErrorStream: This is an error
To validate CSV fields, you can use grep
with regular expressions to check for specific patterns or formats. For example, to check if all lines in a CSV file have exactly 5 comma-separated fields, you can use the following command:
grep -E "^[^,]+,[^,]+,[^,]+,[^,]+,[^,]+$" yourfile.csv
This command will print only the lines that match the specified pattern, indicating valid CSV fields.
Filtering logs by error level is a common use case for grep
. To filter logs for lines containing the word “ERROR”, you can use the following command:
grep "ERROR" logs.txt
This command will print all lines from logs.txt
that contain the word “ERROR”, allowing you to focus on error messages.
When searching through source code, grep
can be used to find specific functions or patterns. For example, to find all occurrences of a function named calculateTotal
in a directory of source code files, you can use the following command:
grep -r "calculateTotal" /path/to/source/code/directory
This command will recursively search through all files in the specified directory and print the lines that contain the function name.
Regular expressions can be used to match URLs or email addresses in text. For example, to find all lines in a file that contain a URL, you can use the following command:
grep -E "https?://[^ ]+" yourfile.txt
This command will print all lines that contain a URL starting with “http://” or “https://”.
Stopwords are common words like “the”, “and”, etc., that do not carry much meaning in a sentence. To filter out lines containing stopwords, you can use grep
with a list of stopwords. For example, to filter out lines containing the stopwords “the”, “and”, or “a”, you can use the following command:
grep -vE "the|and|a" yourfile.txt
This command will print all lines that do not contain any of the specified stopwords.
Regular expressions can be used to detect near-duplicate entries or misspellings by matching similar patterns. For example, to find lines that contain words with a single character difference, you can use the following command:
grep -E "(\w)\1" yourfile.txt
This command will print all lines that contain words with a single character repeated, indicating potential near-duplicates or misspellings.
Regular expressions can be used to match named entities or common phrases in text. For example, to find all lines that contain a specific phrase like “named entity recognition”, you can use the following command:
grep -E "named entity recognition" yourfile.txt
This command will print all lines that contain the specified phrase, allowing you to focus on relevant information.
Continuous integration and deployment pipelines can produce thousands of lines of log output. grep
is indispensable for quickly finding the source of a failure. You can chain grep
commands with -v
to exclude routine “noise” and focus on critical errors.
Imagine a verbose build log named build.log
. You want to find error messages but exclude common warnings about deprecation.
grep "ERROR" build.log | grep -v "DEPRECATED"
This pipeline first selects all lines containing “ERROR” and then filters out any of those lines that also contain “DEPRECATED”, helping you zero in on the actionable failures.
System administrators frequently use grep
to parse logs generated by services. On modern Linux systems using systemd
, logs are managed by journalctl
. You can pipe its output to grep to quickly diagnose service issues.
To find all log entries for the NGINX web server that contain the word “failed” (case-insensitively):
journalctl -u nginx.service | grep -i "failed"
This one-line command is often the first step in troubleshooting a failing system service.
A common security misstep is committing credentials or API keys to a code repository. grep
can perform a quick, recursive scan of a directory to look for these secrets.
To search recursively (-r
) through the current directory for common patterns like API_KEY
, ignoring case (-i
):
grep -r -i "API_KEY" .
This will print every file and line number where the pattern is found. While not a replacement for dedicated secret-scanning tools, it’s an excellent first line of defense for preventing accidental exposure of sensitive data.
grep
in the Age of AIWhile grep
is a command-line classic created in the 1970s, its relevance has not diminished in the modern era of AI. Its role has evolved from being a simple search utility into a vital component within a sophisticated ecosystem of developer tools. Today, grep
serves as a high-speed foundational tool for data manipulation and a perfect complement to the cognitive power of AI. This section explores the dynamic relationship between grep
and AI, highlighting how this decades-old command both enhances and is enhanced by cutting-edge technology.
Mastering the syntax of regular expressions has always been a significant hurdle for developers. Complex patterns can be notoriously difficult to compose and even harder to decipher. Modern AI assistants act as a powerful bridge, making the full power of regex accessible to everyone.
AI-Powered Regex Generation: Imagine you need to validate a username according to a complex set of rules: it must be 8-16 characters long, start with a letter, contain at least one number, and allow underscores but not at the beginning or end. Crafting this regex by hand is a meticulous, error-prone process. With an AI assistant like GitHub Copilot or ChatGPT, you can simply describe these requirements in plain English. The AI translates your intent into a precise, working pattern, often providing a version compatible with grep
’s specific regex flavor. This transforms the task from a frustrating puzzle into a simple, conversational exchange.
AI for Regex Explainability: Even more common is inheriting a script containing a cryptic regex like ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$
. At a glance, this is nearly unreadable. Instead of spending an hour painstakingly decoding it, you can paste it into an AI tool and ask for an explanation. The AI will act as a translator, breaking it down piece by piece: “(?=.*[a-z])
is a positive lookahead ensuring at least one lowercase letter exists…” This capability is invaluable for debugging, refactoring legacy code, and accelerating the learning process for junior developers.
grep
’s Role in AI and Machine LearningIn the domain of AI and ML, data is the raw material, and its quality dictates the success of the final model. Before sophisticated algorithms can even begin their work, vast datasets must be filtered, sanitized, and structured. In this crucial preprocessing stage, grep
excels as a powerful, high-performance tool for bulk data cleanup.
Data Preprocessing and Cleaning: Consider the challenge of preparing a massive 50GB text dataset for training a natural language model. This raw data, scraped from the web, is inevitably messy. It might contain leftover HTML tags, malformed JSON snippets, or lines with non-UTF-8 characters. Running a delicate Python script on this raw file is inefficient and risky—a single bad line could cause the entire process to fail.
grep
provides a robust, fault-tolerant first line of defense. You can use it in a pipeline to perform critical cleaning tasks at incredible speed:
grep '"text":'
extracts only the lines containing the desired data field.grep -v "<!DOCTYPE html>"
quickly strips out any contaminating HTML documents.grep -E "\b(error|failed|exception)\b"
can create a smaller, focused dataset of error-related text for specialized model training.By using grep
to handle this initial, high-volume filtering, you save valuable computational resources and ensure that the subsequent AI/ML tools receive a clean, well-structured dataset, allowing them to operate more efficiently and effectively.
grep
vs. Modern AI ToolsTo understand grep
’s place in the modern toolkit, it’s best to think in terms of trade-offs. grep
is like a razor-sharp scalpel: it performs a specific task, text matching, with unparalleled speed and precision. AI-powered tools are slower but provide a deep, contextual understanding of the entire system.
The table below provides a more detailed comparison:
Feature | grep |
AI-Powered Tools (e.g., Sourcegraph, Copilot) |
---|---|---|
Search Method | Literal and pattern-based text matching. It finds sequences of characters. | Semantic, contextual, and conceptual search. It finds meaning and relationships. |
Awareness | Line-oriented. It has no understanding of code syntax, scope, or structure. | Code-aware. It understands functions, classes, variable scope, and dependencies. |
Core Question | “Does this exact string or pattern exist in this file?” | “Where in the codebase is this concept implemented?” |
Speed | Extremely fast for known patterns. Optimized for raw text processing. | Slower, but can perform complex, abstract queries that grep cannot. |
Universality | Universal. Available by default on virtually every Unix-like system. | Platform-specific. Requires installation, configuration, and often a network connection. |
Code Search: If you need to find every occurrence of the function name getUserById
, grep -r "getUserById"
is the perfect tool. But what if you need to find all the places in a large codebase that handle user password resets? The relevant functions might be named resetUserPassword
, updateCredentials
, or handleAuthTokenInvalidation
. grep
would require you to know and search for every possible permutation. An AI-powered tool understands the concept of a password reset. You can ask it, “show me functions related to password resets,” and it will identify all the relevant code blocks, regardless of their specific names.
Log Analysis: Using grep "FATAL"
to find critical errors in a log file is a daily task for many engineers. It’s fast and effective for finding known problems. However, consider a more harmful issue: a subtle memory leak that causes system performance to degrade over days. There is no single “ERROR” line. The problem is hidden within a pattern of thousands of seemingly normal log entries. This is where AI-driven log analysis platforms excel. They can ingest terabytes of log data and detect statistical anomalies, identifying that a specific sequence of events, while not an error itself, correlates with increased memory usage. grep
helps you find the needles you know are in the haystack; AI helps you discover the needles you never knew existed.
When using regex operators like *
, +
, or ?
, it’s essential to escape them properly to avoid unexpected matches. For example, if you want to match the literal character *
, you should escape it with a backslash (\*
). Similarly, to match the literal characters +
or ?
, escape them with a backslash (\+
or \?
).
Example command to match a literal *
character:
grep -E "a\*" yourfile.txt
To match empty lines or lines with only whitespace, you can use the following regex pattern:
grep -E "^\s*$" yourfile.txt
This pattern matches lines that start (^
) and end ($
) with any whitespace characters (\s*
).
To match tabs (\t
) or carriage returns (\r
) in your text, you can use the following commands:
# Match lines containing tabs
grep -E "\t" yourfile.txt
# Match lines containing carriage returns
grep -E "\r" yourfile.txt
Note that in some cases, you might need to use the -E
option to enable extended regex patterns, which allow you to use more advanced regex features.
Command | Description | Features | Use Cases | Sample Command |
---|---|---|---|---|
grep | Basic pattern matching | Supports basic regex | General pattern matching | grep "pattern" file.txt |
egrep | Extended pattern matching | Supports extended regex | Complex pattern matching | egrep "pattern" file.txt |
fgrep | Fixed pattern matching | No regex support | Matching fixed strings | fgrep "pattern" file.txt |
Note: The main difference between these commands is the type of pattern matching they support. grep
supports basic regex, egrep
supports extended regex, and fgrep
does not support regex at all.
grep
is not well-suited for handling multiline patterns due to its line-oriented nature. However, there are alternative tools that can effectively handle such patterns. awk
and perl
are two popular options that can be used to search for patterns spanning multiple lines.
awk
is a powerful text processing tool that can be used to match patterns across multiple lines. It allows you to define a pattern to match and then perform actions on the matched lines. For example, to find lines that contain a pattern across multiple lines, you can use the following command:
awk '/pattern/ {print $0}' yourfile.txt
This command will print all lines that match the specified pattern. Note that awk
can also be used to perform more complex operations on the matched lines, such as printing the entire block of text that matches the pattern.
perl
is another powerful tool that can be used to handle multiline patterns. It offers a more flexible and expressive way of matching patterns using its built-in regular expression engine. For example, you can use the following command to find lines that contain a pattern across multiple lines:
perl -0777 -ne 'print if /pattern/s' yourfile.txt
This command tells perl
to read the file in “slurp” mode (-0777
), which allows it to read the entire file into memory at once. The -ne
option specifies that the script should be executed for each line in the file. The print if /pattern/s
statement matches the pattern across multiple lines (due to the s
modifier) and prints the entire block of text that matches.
Both awk
and perl
offer more advanced features and flexibility than grep
when it comes to handling multiline patterns, making them ideal alternatives for such tasks.
grep
and egrep
are both used for pattern matching, but they differ in the type of patterns they support. grep
supports basic regular expressions, while egrep
supports extended regular expressions, which allow for more advanced pattern matching.
Yes, you can use grep
to search across multiple files by specifying multiple file names or using wildcards. For example:
grep "pattern" file1.txt file2.txt
or
grep "pattern" *.txt
To grep for lines that do not match a pattern, use the -v
option. For example:
grep -v "pattern" yourfile.txt
This will print all lines that do not contain the specified pattern.
To include line numbers in grep
output, use the -n
option. For example:
grep -n "pattern" yourfile.txt
This will print the line numbers along with the lines that match the specified pattern.
There could be several reasons why your grep
regex is not working as expected. Here are a few common issues to check:
grep
command (e.g., -E
for extended regex).To search for a pattern that includes whitespace or special characters, you need to properly escape these characters in your regex pattern. For example, to search for a pattern that includes whitespace, use the following command:
grep "pattern\ with\ whitespace" yourfile.txt
Similarly, to search for a pattern that includes special characters, escape them using a backslash (\
). For example:
grep "pattern\ with\ special\ characters" yourfile.txt
In this tutorial, you’ve moved beyond simple keyword searches to harness grep as a powerful tool for text processing. You started with basic literal matching and common command-line options, then progressed through the different flavors of regular expressions such as Basic (BRE) and Extended (ERE) to the advanced patterns available in Perl-Compatible Regular Expressions (PCRE). By exploring real-world scenarios like filtering logs, scanning source code, and preparing data for AI workflows, you have seen how grep
remains an essential utility in any modern toolkit.
Mastering grep and its regular expression syntax is a fundamental skill that dramatically enhances your ability to work with text data on the command line. It allows you to build efficient, precise, and automated workflows, turning complex data-sifting tasks into simple commands.
To further improve your skills, we recommend checking out the following tutorials:
By exploring these tutorials, you’ll gain a deeper understanding of grep
, regular expressions, and other essential Linux tools, enabling you to tackle a wide range of tasks with confidence.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Former Senior Technical Writer at DigitalOcean, specializing in DevOps topics across multiple Linux distributions, including Ubuntu 18.04, 20.04, 22.04, as well as Debian 10 and 11.
I help Businesses scale with AI x SEO x (authentic) Content that revives traffic and keeps leads flowing | 3,000,000+ Average monthly readers on Medium | Sr Technical Writer @ DigitalOcean | Ex-Cloud Consultant @ AMEX | Ex-Site Reliability Engineer(DevOps)@Nutanix
With over 6 years of experience in tech publishing, Mani has edited and published more than 75 books covering a wide range of data science topics. Known for his strong attention to detail and technical knowledge, Mani specializes in creating clear, concise, and easy-to-understand content tailored for developers.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
I mostly need it for searching snippets of code. Thanks for the writeup!
Great article, thanks!
| The following expression matches the string “free” plus one or more characters that are not whitespace:
grep -E "free[^[:space:]]+" GPL-3
This wouldn’t match tab whitespace. For it to match tab whitespaces, you’ll need to make :space: into :blank: like so:
grep -E "free[^[:blank:]]+" GPL-3
Hi , i need a quick answer to this question, I have the following two string where i search for 20141107(Date) soon after 5 0r 6 characters after start, and if it comes latter, it should be ignored. in simple words, i believe there is no match for 20141107 in below two string. please help me write a regular expression for this.
FSDE5201410201411074218GCDR FSDE54201410201411074218GCDR
How can i make RE for following ,
function any_fun_name**(any_arq,more_arq,…){** /// Code }
i want to match pattern for font in bold,
valid is,
function abc(){ }
function abvvdd(dfd,dfd,dfd){ }
Not valid is
function adfhdf() { }
thanks
i mostly need it for searching special characters . i need search for “sometext *” sometext space star
can you give me the command ? thanks
Nice Article , can we add this too ?
Usage 8: Search for multiple patterns for single word.
Normally we search for only one pattern.But with fgrep we can give multiple patterns for searching string.
Usage 9: Search for String in Zip Files.
In linux,we zip the files with extension as “.gz”.We can search in Zip file by using above command.
Thank you for providing explanations, demonstrations and hands-on material to experiment with…
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.