Regex becomes much easier to maintain when you treat it as a small, testable program rather than a mysterious line of punctuation. This practical regex cheat sheet explains the core syntax, provides copy-ready regular expression examples, and gives you a repeatable workflow for testing, debugging, and safely updating patterns as requirements change.
Overview
A regular expression describes a pattern that text must match. You can use one to find text, validate an input, extract a value, or replace part of a string. The same expression may behave differently depending on the language, regex engine, flags, and input boundaries, so always test a pattern in the environment where it will run.
Core regex syntax reference
| Syntax | Meaning | Example |
|---|---|---|
. | Any character except a line terminator in many engines | a.c matches abc and a-c |
\d | A digit in many engines | \d{4} matches four digits |
\w | A word character, usually letters, digits, or underscore | \w+ matches a word-like sequence |
\s | Whitespace | \s+ matches one or more spaces or line breaks |
[abc] | One character from the set | [aeiou] matches one vowel |
[^abc] | One character not in the set | [^,]+ matches non-comma characters |
^ | Start of a string or line, depending on mode | ^Error |
$ | End of a string or line, depending on mode | done$ |
* | Zero or more repetitions | ab* matches a, ab, and abb |
+ | One or more repetitions | \d+ |
? | Zero or one, or a lazy modifier after a quantifier | https? matches HTTP or HTTPS |
{n,m} | Between n and m repetitions | \d{2,4} |
| | Alternation | cat|dog |
(...) | Capturing group | (\d{4})-(\d{2}) |
(?:...) | Non-capturing group | https?:// |
Escape punctuation when you need its literal meaning. For example, \. matches a period, while an unescaped period usually means “any character.” Likewise, \+ matches a plus sign instead of applying the one-or-more quantifier.
Anchors, groups, and lookarounds
Anchors are essential for validation. A search expression such as \d+ can find digits inside a longer string. A validation expression should normally describe the whole input, such as ^\d+$, although the exact full-string anchor syntax varies by engine.
Groups let you organize alternatives and capture useful values. For example, ^(\d{4})-(\d{2})-(\d{2})$ captures year, month, and day separately. Use a non-capturing group when you only need parentheses for structure: ^(?:cat|dog)$.
Lookarounds check nearby text without including it in the match. A positive lookahead, such as ^(?=.*[A-Z]).+$, requires an uppercase letter somewhere in the input. A negative lookahead, such as ^(?!.*password).+$, rejects an input containing a particular sequence. Lookbehind support differs more widely between languages, so verify compatibility before using it in shared code.
Checklist by scenario
When validating a complete field
- Define the accepted input in plain language before writing syntax.
- Use start and end boundaries so extra text cannot be accepted accidentally.
- Choose whether empty values are valid; do not let quantifiers decide by accident.
- Test minimum, maximum, typical, malformed, and whitespace-containing values.
- Keep business rules that require complex logic outside the regex when that improves readability.
For example, a simple four-digit code could be represented as ^\d{4}$. If the code must use ASCII digits specifically, use an explicit character class such as ^[0-9]{4}$ when your engine's definition of \d may include additional numeral characters.
When extracting data
- Identify the exact delimiter or boundary around the value.
- Use a capturing group only for values the application needs.
- Decide whether the match should be greedy or lazy.
- Handle repeated matches deliberately rather than assuming one match.
- Confirm how the programming language exposes groups and unmatched optional groups.
A basic key-value pattern such as ^([^=]+)=(.*)$ captures text before the first equals sign and everything after it. It is useful for simple input, but it should not replace a parser when values can contain quoting, escaping, or nested structure.
When searching or replacing
- Use a case-insensitive flag only when case should truly be ignored.
- Use a global or repeated-match option when every occurrence must be changed.
- Prefer word boundaries, such as
\b, when matching a complete word. - Test replacement text separately from the search pattern.
- Check whether replacement syntax uses
$1,\1, or another group reference.
For example, \bTODO\b can find the standalone word without matching a longer word that contains those letters. Boundary behavior can vary for non-ASCII text, so include representative examples from the application.
When working with common formats
Use regular expressions for narrow, clearly defined checks rather than claiming to implement an entire format specification. A practical URL-like check might confirm an allowed scheme and a non-space remainder:
^https?://[^\s]+$
This is not a complete URL parser. It is a deliberately limited rule that may be suitable for an interface with a stated requirement. For email addresses, phone numbers, dates, and URLs, document the accepted subset and test it against real examples. If the format has nesting or escaping rules, a dedicated parser is usually easier to reason about.
What to double-check
Flags and engine behavior
Before copying a pattern between projects, check the supported flags. Common flags include case-insensitive matching, multiline anchors, dot-all behavior, global matching, and Unicode-aware matching. Their names and effects are not identical across languages. In JavaScript, for example, flags are commonly written after a slash, while other languages pass options separately.
String escaping
A regex embedded in source code may be escaped twice: once for the programming language string and once for the regex engine. The pattern \d+ may therefore appear differently in a source string than in a regex tester. If a pattern looks correct in a tester but fails in code, inspect the actual runtime string rather than the source representation.
Greedy matching and boundaries
Quantifiers are generally greedy: they consume as much as they can while still allowing the rest of the pattern to match. A lazy quantifier, such as .*?, consumes as little as possible, but it does not automatically make a pattern safe or precise. Replace broad wildcards with explicit character classes and boundaries whenever the input has a known structure.
Performance and hostile input
Some nested combinations of alternation and repetition can cause excessive backtracking on carefully chosen input. Keep patterns simple, avoid ambiguous nested quantifiers, set reasonable input limits, and test long and adversarial strings when processing untrusted data. A regex tester can help you inspect matches, but it cannot replace testing in the target runtime.
Common mistakes
- Using a search pattern as validation: Without full-input boundaries, valid text may appear inside invalid text.
- Forgetting to escape punctuation: A period, plus sign, question mark, or parentheses may be interpreted as syntax rather than literal text.
- Overusing
.*: Broad wildcards often capture too much and make failures difficult to diagnose. - Confusing groups with character classes:
(abc)means the sequence “abc,” while[abc]means one character from that set. - Assuming
\wmeans every letter: Its behavior is engine- and mode-dependent and commonly includes digits and underscore. - Writing one enormous validator: Split independent rules into readable checks when a single expression becomes difficult to review.
- Skipping negative tests: A pattern is not ready because it matches valid examples; it must also reject plausible invalid ones.
- Trusting generated regex without review: AI coding assistants and online generators can provide a starting point, but you still need to inspect boundaries, flags, escaping, and performance.
When debugging, reduce the expression to the smallest failing case. Start with a literal, add one character class or quantifier at a time, and compare the expected match with the actual match. Keep a small test table containing inputs, expected results, and captured groups. This turns an opaque failure into a sequence of verifiable decisions.
When to revisit
Revisit a regex whenever the accepted input changes, the application moves to another language or runtime, or a dependency changes how text is normalized. Also review patterns before a major release, after a bug involving malformed input, and whenever users begin submitting new scripts, whitespace styles, or delimiter formats.
Use this maintenance checklist:
- Write the new requirement as examples before modifying the pattern.
- Add passing and failing cases to automated tests.
- Check anchors, flags, Unicode behavior, and source-code escaping.
- Run long-input and worst-case tests if input is externally controlled.
- Update the comment or documentation that defines the accepted format.
- Ask whether a parser or ordinary code would now be clearer than regex.
For a broader reference, pair this guide with the Regex Cheat Sheet for Developers. If you are troubleshooting a failing implementation, the web application debugging workflow provides a useful process for isolating the problem. Keep this checklist near your code review or test workflow, and update it whenever the input contract changes rather than waiting for a surprising production match.