Skip to content
Development

What Is a Regular Expression? Regex Patterns Explained With Examples

Build a pattern from a clear text requirement rather than treating the punctuation as a shortcut.

What Is a Regular Expression? Regex Patterns Explained With Examples

Key takeaways

  • A regular expression describes text patterns for matching, extraction, and replacement.
  • Searching within a string and checking the entire input require different boundaries.
  • Flags and engine-specific behavior are part of the pattern's meaning.
  • A match does not establish semantic validity, and short patterns can still be expensive.

A regular expression, usually called regex, is a pattern used to search, extract, or transform text.

Instead of searching for one exact string, it describes a family of strings. For example, a support reference might consist of two uppercase letters, a hyphen, and four digits.

That requirement can match AB-4821 and ZX-0007 without listing every possible reference.

The examples here use JavaScript. Other regex engines can differ in syntax and behavior.

Build the Pattern From Small Parts

[A-Z]{2}-[0-9]{4}

Read the expression from left to right:

PartMeaning
[A-Z]One uppercase ASCII letter
{2}Repeat the preceding item exactly twice
-A literal hyphen in this position
[0-9]One ASCII digit
{4}Repeat it exactly four times

The JavaScript regex guide documents these building blocks.

A character class selects one character. It does not match the whole sequence written inside the brackets.

Searching and Whole-Input Checking Differ

A search can find the reference inside a sentence:

const match = /[A-Z]{2}-[0-9]{4}/.exec("Reference: AB-4821");
console.log(match?.[0]); // AB-4821

For a form field that should contain only the reference, boundaries matter:

const referencePattern = /^[A-Z]{2}-[0-9]{4}$/;

function isReference(value) {
  return typeof value === "string" &&
    value.length === 7 &&
    referencePattern.test(value);
}

This version explicitly requires seven characters as well as the pattern. It rejects surrounding spaces and line breaks.

Normalization is a separate product decision. If spaces should be trimmed, do so deliberately and explain that behavior rather than letting different callers normalize differently.

Capturing Groups Return Useful Pieces

Parentheses can capture part of a match:

const match = /^([A-Z]{2})-([0-9]{4})$/.exec("AB-4821");

if (match) {
  console.log(match[1]); // AB
  console.log(match[2]); // 4821
}

The captured digits are text. Converting them to a number would remove leading zeros, which may be wrong for a reference identifier.

Use captures when later code needs the components. Use noncapturing groups, written (?:...), when grouping is needed only to organize the pattern.

A captured prefix still does not prove that the support system recognizes that prefix.

Quantifiers Specify How Much

Common repetition forms include + for one or more, * for zero or more, ? for optional, and a range such as {2,5}.

The distinction between zero and one matters. A field intended to contain digits should not accidentally accept an empty string because its pattern used *.

Alternation uses | to express alternatives. Group it carefully so surrounding conditions apply to the intended alternatives.

The regex builder guide provides a more guided way to construct patterns.

Flags Change Behavior

An i flag makes matching case-insensitive. A g flag supports finding successive matches. Other flags affect line boundaries, dot matching, and Unicode behavior.

JavaScript expressions with g or y maintain a lastIndex position during operations such as test(). Reusing one as a simple validator can produce surprising alternating results.

The test() documentation explains that stateful behavior. The reference validator above does not need either flag.

Also remember that [A-Z] is an ASCII range, not a definition of all letters in every language.

Matching Shape Is Only One Check

A date-shaped pattern can accept an impossible date. A reference-shaped string can name an order that does not exist.

After pattern matching, application logic may need to check allowed values, ownership, or database records.

For nested JSON or HTML, use a parser to recover structure, then apply small patterns to appropriate values. The regex-versus-parsing comparison explains this division.

Consider Failure Cases and Cost

Backtracking engines can spend excessive time exploring ambiguous repetitions. A pattern such as ^(a+)+$ can perform badly on some long, nearly matching inputs.

OWASP’s ReDoS explanation describes this class of problem.

Keep untrusted input bounded and avoid needlessly ambiguous patterns. Review failures as well as successes: missing digits, extra characters, empty input, unexpected Unicode, and long near-matches.

For the support reference, a small pattern plus an explicit input contract is easy to explain. That clarity is more valuable than a clever expression whose accepted inputs nobody can confidently describe.

Define what should match and what should fail before trying to shorten the expression.
Top