Skip to main content

Regex Cheatsheet

By Dejan Panovski Updated on Download PDF

Regex syntax and examples for Linux tools, including metacharacters, quantifiers, character classes, anchors, groups, BRE, ERE, and PCRE

A regular expression describes a text pattern instead of a fixed string. This cheatsheet shows how common patterns change between grep, sed, awk, Vim, Bash, and PCRE-based tools.

Metacharacters

Characters that mean something other than themselves.

PatternDescription
.Any single character except a newline
*Zero or more of the item before it
[...]Any one character from the set
[^...]Any one character not in the set
^Start of the line
$End of the line
\Escape a character or begin a special sequence, depending on the regex flavor

Most other characters match themselves. Line-based tools such as grep, sed, and awk read one line at a time, so . never matches the line ending.

Anchors and Word Boundaries

Tie a pattern to a position instead of a character.

PatternDescription
^errorLine starts with error
done$Line ends with done
^exact$Match the whole line
^$Match an empty line
\<wordStart of a word (GNU tools and Vim)
word\>End of a word
\bword\bWord boundary on both sides (GNU and PCRE)
\BAny position that is not a word boundary

Anchors match a position of zero width, so they never consume a character. In awk, \b means a backspace rather than a word boundary; gawk provides \y instead.

Bracket Expressions

Match one character out of a set you define.

PatternDescription
[abc]One a, b, or c
[^abc]Any character except a, b, or c
[a-z]One lowercase letter
[0-9a-fA-F]One hexadecimal digit
[]abc]Include a literal ] by putting it first
[abc-]Include a literal - by putting it last
[a^]^ is literal when it is not first

Most metacharacters lose their meaning inside brackets, so [.*] matches a dot or an asterisk. Ranges follow the current locale, so use LC_ALL=C or a POSIX class when you need predictable results.

POSIX Character Classes

Portable, locale-aware sets that go inside a bracket expression.

ClassMatches
[[:digit:]]Digits
[[:alpha:]]Letters
[[:alnum:]]Letters and digits
[[:lower:]] [[:upper:]]Lowercase and uppercase letters
[[:space:]]Whitespace, including tabs and newlines
[[:blank:]]Spaces and tabs only
[[:punct:]]Punctuation characters
[[:xdigit:]]Hexadecimal digits
[[:print:]] [[:graph:]]Printable, and printable except space
[[:cntrl:]]Control characters

The double brackets are not a typo. The class itself is [:digit:], and the outer brackets are the bracket expression that holds it, so [[:digit:]_] matches a digit or an underscore.

Quantifiers

Say how many times the preceding item repeats.

PatternDescription
a*Zero or more a
a\+ / a+One or more, BRE and ERE forms
a\? / a?Zero or one
a\{3\} / a{3}Exactly three
a{3,}Three or more
a{,3}Up to three (GNU extension for {0,3})
a{2,4}Between two and four
.*Any run of characters, including none

Quantifiers are greedy and take the longest match available. In a basic regular expression, a * at the very start of the pattern is a literal asterisk because there is nothing for it to repeat.

Groups, Alternation, and Backreferences

Treat several characters as one unit and reuse what they matched.

PatternDescription
(ab)+ERE group repeated one or more times
\(ab\)\+The same group in BRE
cat|dogERE alternation, either side matches
cat\|dogThe same alternation in GNU BRE
^(a|b)c$Alternation limited to the group
\1Whatever group 1 matched
\(.\)\1Any character repeated twice

Groups are numbered from left to right by their opening parenthesis. Backreferences are part of POSIX BRE, and GNU grep and GNU sed also accept them in extended patterns. POSIX ERE and awk do not support backreferences. In a sed replacement, \1 inserts group 1 and & inserts the whole match.

Escaping Special Characters

Match a metacharacter as an ordinary character.

PatternDescription
\.A literal dot
\\A literal backslash
\* \[ \^ \$The literal symbol
[.]A dot, escaped by a bracket expression instead
grep -F 'a.b'Treat the whole pattern as a fixed string
\Q...\EQuote a run of characters in PCRE

Quote patterns with single quotes so the shell passes the backslashes through untouched. Inside double quotes, the shell expands $ and consumes some backslashes before the tool ever sees the pattern.

Shorthand Classes

Short names for common sets, provided as extensions rather than by POSIX.

PatternMatches and Availability
\w \WWord and non-word characters in GNU grep, GNU sed, gawk, PCRE, and Vim; the exact character set varies by engine and locale
\s \SWhitespace and non-whitespace in GNU grep, GNU sed, gawk, PCRE, and Vim
\d \DDigits and non-digits in PCRE and Vim; not defined by POSIX BRE or ERE
\h \vHorizontal and vertical whitespace in PCRE; Vim assigns different meanings to both sequences

Do not use \d with grep’s basic or extended syntax. GNU grep documents an escaped ordinary character such as \d as unspecified, and other grep implementations may interpret it differently. Use [[:digit:]], [0-9], or grep -P instead.

PCRE Extras

Available with grep -P and other Perl-compatible engines.

PatternDescription
.*? +? ??Lazy quantifiers that take the shortest match
(?:...)Group without capturing it
(?<name>...)Named capture group
(?=...)Lookahead, text must follow
(?!...)Negative lookahead
(?<=...)Lookbehind, text must precede
(?<!...)Negative lookbehind
(?i)Case-insensitive from this point on
\KDrop everything matched so far from the result

Lookarounds check their surroundings without adding them to the match, which pairs well with grep -oP. None of this works in sed or awk, and grep -P needs a build with PCRE support.

BRE, ERE, and PCRE

The same idea written three ways.

FeatureSyntax by Flavor
GroupingBRE \(ab\); ERE and PCRE (ab)
AlternationGNU BRE a\|b; ERE and PCRE a|b
One or moreGNU BRE a\+; ERE and PCRE a+
OptionalGNU BRE a\?; ERE and PCRE a?
IntervalBRE a\{2,4\}; ERE and PCRE a{2,4}
BackreferenceBRE and PCRE \1; GNU grep and GNU sed also accept \1 in ERE, but POSIX ERE and awk do not
\d and lookaroundPCRE supports both; BRE and ERE do not
Default inBRE: grep, sed; ERE: grep -E, sed -E, awk; PCRE: grep -P

In GNU grep, BRE and ERE provide the same pattern-matching functionality with different notation. The characters ?, +, (), {}, and | are special without backslashes in ERE and with backslashes in GNU BRE. This equivalence does not extend to POSIX ERE backreferences or PCRE-only features.

Regex in grep

Pick the flavor with a flag.

CommandDescription
grep 'pattern' fileBasic regular expression, the default
grep -E 'pattern' fileExtended regular expression
grep -P 'pattern' filePerl-compatible regular expression
grep -F 'pattern' fileNo regex at all, fixed string
grep -o 'pattern' filePrint only the matched text
grep -w 'pattern' fileRequire word boundaries around the match
grep -i 'pattern' fileIgnore case
grep -v 'pattern' filePrint the lines that do not match

Use -o while building a pattern to see exactly what it captures. GNU grep 3.8 and later print a warning for egrep and fgrep, so write grep -E and grep -F instead.

Regex in sed

Patterns select lines, and the same syntax drives substitutions.

CommandDescription
sed 's/old/new/' fileSubstitute using a basic regular expression
sed -E 's/[0-9]+/N/g' fileExtended syntax, with -r as a synonym
sed -n '/error/p' filePrint only matching lines
sed '/^$/d' fileDelete every empty line
sed 's/\(a\)\(b\)/\2\1/' fileSwap two captured groups
sed 's/word/[&]/' fileWrap the whole match in brackets
sed 's/error/ERROR/gI' fileReplace every match, ignoring case
sed -E 's/(\w+)/\U\1/' fileUppercase group 1 with a GNU escape

The delimiter does not have to be a slash. Writing sed 's|/usr/bin|/usr/local/bin|' avoids escaping every slash in a path.

Regex in awk

Patterns are extended regular expressions and sit between slashes.

CommandDescription
awk '/error/' filePrint lines matching the pattern
awk '$1 ~ /^web/' fileMatch a single field
awk '$3 !~ /ok/' fileMatch fields that fail the pattern
awk '/start/,/stop/' filePrint an inclusive range of lines
awk '{ gsub(/[0-9]+/, "N"); print }' fileReplace every match on the line
awk '{ sub(/^ +/, ""); print }' fileReplace the first match only
awk 'match($0, /[0-9]+/) { print substr($0, RSTART, RLENGTH) }' fileLocate a match and extract it
gawk '{ gsub(/\yroot\y/, "USER"); print }' fileWord boundaries in gawk

Awk always uses extended syntax, so +, ?, and {n,m} work without a backslash. When the pattern is a string rather than a /.../ literal, every backslash needs doubling, so gsub(/\./, "-") becomes gsub("\\.", "-").

Regex in Vim

Vim uses its own flavor, close to ERE once you turn on very magic mode.

PatternDescription
/patternSearch forward in the file
:%s/old/new/gReplace every match in the file
a\+One or more, since + needs a backslash by default
\vVery magic mode, so +, ?, (, and | work unescaped
\v\d+Digits in very magic mode
\<word\>Whole word match
price: \zs\d\+Start the match after \zs, end it at \ze
\cerrorIgnore case for this pattern

Very magic mode is the shortcut worth remembering. Writing :%s/\v(\w+), (\w+)/\2 \1/g to swap two fields keeps a pattern readable instead of filling it with backslashes.

Regex in Bash

The =~ operator inside [[ ]] takes an extended regular expression.

SnippetDescription
[[ $ip =~ ^[0-9.]+$ ]]Test a string against a pattern
[[ ! $name =~ ^[a-z] ]]Negate the test
re='^v([0-9]+)\.([0-9]+)$'Keep the pattern in a variable
[[ $tag =~ $re ]]Use the variable unquoted so it stays a regex
${BASH_REMATCH[0]}The whole match
${BASH_REMATCH[1]}The first capture group
case $file in *.txt) ;; esacA reminder that case uses globs, not regex

Quoting the right-hand side turns the pattern into a literal string, so [[ abc =~ "a.c" ]] fails while [[ abc =~ a.c ]] succeeds. Store the pattern in a variable when it contains spaces or quotes.

Common Patterns

Working starting points to copy and adjust.

PatternMatches
grep -E '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b'Anything shaped like an IPv4 address
grep -P '\b((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\b'An IPv4 candidate with each octet under 256
grep -E '[[:alnum:]._%+-]+@[[:alnum:].-]+\.[[:alpha:]]{2,}'An email-shaped address
grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2}'An ISO date such as 2026-08-28
grep -E '#[0-9a-fA-F]{6}\b'A six-digit hex color
grep -nE '[[:space:]]+$'Trailing whitespace, with line numbers
grep -cE '^[[:space:]]*$'Count blank lines
grep -E '^[[:space:]]*#'Commented-out configuration lines
grep -vE '^[[:space:]]*(#|$)'Everything except comments and blank lines
grep -E '\b([[:alpha:]]+) \1\b'A word accidentally repeated twice
grep -oE '"[^"]*"'A double-quoted string, quotes included
grep -oP 'user=\K\S+'The value after a user= key, key excluded

The address patterns describe a shape rather than validate it. Use them to pull candidates out of logs, and check the results with a real parser when correctness matters.

Troubleshooting

Common regex problems and what to check first.

ProblemCheck
\d fails or behaves unexpectedlyBRE and ERE do not define \d; use [[:digit:]], [0-9], or grep -P
+ or ? matched literallyThe pattern is basic syntax; escape them as \+ and \?, or switch to grep -E
Alternation found nothingERE takes a bare pipe, BRE takes an escaped one; grep -E is the simpler fix
The shell changed the patternWrap the pattern in single quotes so backslashes and $ survive
[a-z] also matched uppercaseRange order follows the locale; use LC_ALL=C or [[:lower:]]
Lookahead or lookbehind rejectedBRE and ERE do not support them; use grep -P, or the engine’s own syntax such as Vim’s \@=
grep -P is not supportedThe build lacks PCRE; use pcre2grep, perl -ne, or rewrite the pattern
\b did nothing in awkAwk reads \b as a backspace; use \y in gawk or \< and \>
The match ran too farQuantifiers are greedy; use a negated class such as [^"]*, or a lazy .*? with -P
Intervals matched literally in VimVim needs \{2,4} in magic mode, or \v first

Longer walkthroughs and per-tool references.

GuideDescription
Regular Expressions BasicsLearn the building blocks from the ground up
Regular Expressions in GrepEvery grep flavor with worked examples
grep CheatsheetSearch options, recursion, and context output
sed CheatsheetSubstitution, addresses, and in-place editing
awk CheatsheetFields, patterns, actions, and built-in variables
Vim CheatsheetMotions, editing, search, and replace