UseToolSuite UseToolSuite

Regex Cheat Sheet: Quick Reference for Developers

A compact regex cheat sheet covering syntax, quantifiers, anchors, groups, lookaheads, and common patterns. Bookmark this for daily reference.

Necmeddin Cunedioglu Necmeddin Cunedioglu 8 min read
Part of the Regular Expressions: The Complete Guide series

Practice what you learn

Regex Tester

Try it free →

Regex Cheat Sheet: The Ultimate Guide for Developers

Regular Expressions (Regex or RegExp) are sequences of characters that define a search pattern. While they might look like line noise or random characters to the uninitiated, they are arguably one of the most powerful text processing tools in a developer’s arsenal. From validating emails to parsing large server logs, mastering regex is a superpower.

This guide goes beyond a simple reference. Bookmark this page and use it alongside our Regex Tester for interactive testing, but also read on to understand how regex engines work, how to optimize them, and how to avoid catastrophic failures.

1. Character Classes & Fundamentals

At the heart of regex is the ability to match specific types of characters without hardcoding them. Character classes define sets of characters that can fulfill a match at a given position.

PatternMatchesExample
.Any character except newlinea.c → abc, a1c
\dDigit (0-9)\d+ → 123
\DNon-digit\D+ → abc
\wWord character (a-z, A-Z, 0-9, _)\w+ → hello_1
\WNon-word character\W → @, #
\sWhitespace (space, tab, newline)\s+ → spaces, tabs
\SNon-whitespace\S+ → hello
[abc]Any of a, b, or c[aeiou] → vowels
[^abc]NOT a, b, or c[^0-9] → non-digit
[a-z]Range a to z[A-Za-z] → letters

Performance Tip: Using specific character classes like [a-zA-Z] is generally faster than relying on . with lookarounds, as it allows the regex engine to immediately discard invalid characters. Moreover, when you use a negated character class like [^"], you dramatically speed up parsing of strings because the engine does not have to guess where the closing quote might be.

2. Quantifiers: Controlling Repetition

Quantifiers dictate how many times the preceding element should be matched. They are the engine of repetition in regular expressions.

PatternMeaningExample
*0 or more\d* → "", 123
+1 or more\d+ → 1, 123
?0 or 1 (optional)colou?r → color, colour
{3}Exactly 3\d{3} → 123
{2,4}2 to 4\d{2,4} → 12, 1234
{2,}2 or more\d{2,} → 12, 12345

Greedy vs. Lazy Matching

By default, quantifiers are greedy—they consume as much text as possible before giving control to the next part of the pattern. Appending a ? makes them lazy, meaning they consume as little as possible.

Consider the string: <div>First</div><div>Second</div>

  • Greedy: <.+> matches <div>First</div><div>Second</div> (the entire string, because .+ eats up everything until the final >).
  • Lazy: <.+?> matches <div> (stops at the first closing bracket because the .+? stops as soon as the next condition > is met).
PatternMeaningExample
*?0 or more (lazy)".+?" → shortest match
+?1 or more (lazy)".+?" → shortest match

Possessive Quantifiers

Some engines (like Java, PCRE, but NOT JavaScript) support possessive quantifiers (*+, ++, ?+). These act like greedy quantifiers but do not backtrack. Once they consume characters, they hold onto them forever. This can greatly optimize performance in specific cases.

3. Anchors & Boundaries

Anchors don’t match characters; they match positions within the string. This is known as a zero-width assertion.

PatternMatches
^Start of string (or line with m flag)
$End of string (or line with m flag)
\bWord boundary (transition between \w and \W)
\BNon-word boundary

Use Case in Python:

import re

text = "The cat scattered the catch."
# Match 'cat' only as a whole word
matches = re.findall(r'\bcat\b', text)
print(matches) # Output: ['cat']

4. Groups and References

Grouping allows you to apply quantifiers to multiple characters, establish precedence, and extract specific parts of a match.

PatternPurpose
(abc)Capture group
(?:abc)Non-capturing group
(?<name>abc)Named capture group
\1Back-reference to group 1
(a|b)Alternation (OR)

Best Practice: Always use non-capturing groups (?:...) unless you specifically need to extract the matched substring. Capturing groups incur a performance penalty because the engine must store the matched text in memory and keep track of indices.

5. Advanced: Lookahead and Lookbehind (Lookarounds)

Lookarounds allow you to assert that a pattern must (or must not) be preceded or followed by another pattern, without actually consuming those characters in the final match. They are zero-width assertions, just like anchors.

PatternNameMeaning
(?=abc)Positive lookaheadFollowed by “abc”
(?!abc)Negative lookaheadNOT followed by “abc”
(?<=abc)Positive lookbehindPreceded by “abc”
(?<!abc)Negative lookbehindNOT preceded by “abc”

Real-world Password Validation Example (JavaScript): Require a password that is at least 8 characters long, contains at least one uppercase letter, one lowercase letter, and one number.

const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/;
console.log(passwordRegex.test("WeakPass")); // false
console.log(passwordRegex.test("Str0ngPass")); // true

The lookaheads independently scan the string from the beginning ^, checking conditions without consuming the characters, allowing the final [a-zA-Z\d]{8,} to actually match the string.

6. Flags and Modifiers

Flags change the fundamental behavior of the regex engine globally across the pattern.

FlagNameEffect
gGlobalFind all matches rather than stopping at the first
iCase-insensitiveIgnore case differences
mMultiline^ and $ match line boundaries instead of string boundaries
sDotAll. matches newlines (often called single-line mode)
uUnicodeEnable \p{L} Unicode classes and proper surrogate pair handling
yStickyMatches only from the index indicated by the lastIndex property (JS specific)

7. Understanding the Regex Engine Architecture

Understanding how regex engines work matters for writing efficient patterns. Most modern programming languages (JavaScript, Python, Java, PCRE) use NFA (Nondeterministic Finite Automaton) engines. Alternatively, tools like grep and awk use DFA (Deterministic Finite Automaton).

NFA vs. DFA

  • DFA Engines: Text-directed. They read the text character by character and maintain a set of all possible states. They are incredibly fast, linear time O(n), and never backtrack. However, they do not support capturing groups or backreferences.
  • NFA Engines: Regex-directed. They read the regex pattern token by token and try to match it against the input string. They support advanced features like lookarounds and backreferences but can suffer from performance issues due to backtracking.

If an NFA engine reaches a point where multiple paths are possible (due to alternation or quantifiers), it picks one and remembers the other. If the chosen path fails later, the engine backtracks to the remembered state and tries the other path.

graph TD
    A[Start State] -->|Match 'a'| B(State 1)
    B -->|Greedy '.+'| C(State 2)
    C -->|Try to match 'b'| D{Does it match?}
    D -- Yes --> E[Success / Final State]
    D -- No --> F[Backtrack]
    F -->|Restore previous state| C

Catastrophic Backtracking

Catastrophic backtracking occurs when an NFA regex engine gets stuck in a runaway loop of backtracking, consuming 100% of the CPU and causing a Regular Expression Denial of Service (ReDoS).

Consider the pattern ^(a+)+$ against the string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaX.

  1. The outer (a+)+ easily matches all the as.
  2. It hits the X and fails because it expects the end of the string $.
  3. The engine backtracks. It thinks, “Maybe the inner a+ should have matched one fewer a, and the outer + can pick it up.”
  4. It tries every possible permutation of grouping the as. For a string of length 30, this results in over 1 billion backtracks!

How to avoid it:

  • Avoid nested quantifiers: Patterns like (a+)+ or (.*)* are major red flags and security vulnerabilities.
  • Use atomic groups: Supported in PCRE and Java as (?>...). An atomic group prevents the engine from backtracking into that group once it has matched successfully.
  • Be specific: Instead of .*, use specific negated classes like [^"]* if you are trying to match content inside quotes. This prevents the engine from over-matching and subsequently backtracking.

8. Language Integration & Best Practices

Different languages implement regex slightly differently. Here are common examples and best practices across the industry stack.

JavaScript

JavaScript RegExp objects are stateful if the global g flag is used. The lastIndex property tracks the last match position, which can lead to insidious bugs if a single RegExp object is reused across multiple function calls.

const regex = /test/g;
console.log(regex.test("test 1, test 2")); // true (lastIndex moves to 4)
console.log(regex.test("test 1, test 2")); // true (lastIndex moves to 12)
console.log(regex.test("test 1, test 2")); // false (reset to 0)

Best Practice: Prefer string methods like String.prototype.matchAll() or avoid sharing stateful RegExp instances across modules.

Python

Python’s re module automatically caches compiled regular expressions, but for maximum performance in tight loops or large applications, it is idiomatic to use re.compile(). Always use raw strings r"" to prevent Python from interpreting backslashes before the regex engine sees them.

import re

# Compile once, use multiple times
pattern = re.compile(r'\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b', re.IGNORECASE)

emails = ["test@example.com", "invalid-email"]
# Efficiently filter using the pre-compiled pattern
valid_emails = [e for e in emails if pattern.match(e)]

Java

In Java, the Pattern class is thread-safe, but the Matcher class is NOT. Always compile the Pattern statically, and generate a new Matcher for every thread or method invocation.

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class Validator {
    // Compile once globally
    private static final Pattern EMAIL_PATTERN = Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");

    public static boolean isValid(String email) {
        // Create new Matcher per call
        Matcher matcher = EMAIL_PATTERN.matcher(email);
        return matcher.matches();
    }
}

9. Comprehensive Real-world Patterns

Here is a collection of battle-tested, reliable patterns for common use cases.

Email (RFC 5322 standard approximate): 
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

URL (HTTP/HTTPS):         
^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$

IPv4 Address:        
^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$

Strong Password:
^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$

Date (YYYY-MM-DD) strict validation: 
^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$

HEX Color (3, 4, 6, or 8 digits):   
^#?(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$

HTML Tag (extraction, non-greedy):    
<\/?[\w\s="/.':;#-\/\?]+>

Interactive testing: Paste any of these patterns into our Regex Tester to see matches highlighted in real time, analyze the abstract syntax tree (AST), and test against your own sample data.


This article is part of our Regular Expressions Guide series. Check out our other resources to continue mastering string manipulation and text processing algorithms.

Necmeddin Cunedioglu
Necmeddin Cunedioglu Author
8 min read
-- views

Software developer and the creator of UseToolSuite. I write about the tools and techniques I use daily as a developer — practical guides based on real experience, not theory.