BackendBench
Coffee

Unravel โ€บ Java concepts โ€บ Strings and text

Java language

Regular expressions

A regular expression describes a pattern of text.

๐Ÿ”Ž Unravel this example

At a glance

Mental model

A stencil with holes: you slide it over text and it lights up everything that fits, such as "three digits, a dash, four digits".

What happens, in order
  1. 1Pattern p = Pattern.compile("(\\d{3})-(\\d{4})"); Matcher m = p.matcher(text); builds the pattern oncem.find() looks for the next match; m.group(1) reads a captured part.
  2. 2matches() requires the whole string to match; find() looks for a match anywhere; lookingAt() anchors at the start
  3. 3Backslashes must be doubled in Java string literals: the regex \\d is written "\\d"Text blocks and raw patterns make this easier to read.
  4. 4String.replaceAll(regex, replacement) and split(regex) take a regex, not plain text; special characters such as and + must be escaped, or use Pattern.quote.
Remember
Watch out
Forgetting to double backslashesCompiling a pattern inside a loopUsing matches when find is meant (it needs the whole string)Splitting on Running an unbounded pattern on untrusted input
Example (highlighted lines explain it)
private static final Pattern ORDER_ID = Pattern.compile("ORD-(?<year>\\d{4})-(?<seq>\\d+)");static Optional<String> yearOf(String text) {    Matcher m = ORDER_ID.matcher(text);    return m.find() ? Optional.of(m.group("year")) : Optional.empty();}
  1. line 1 uses Pattern, the core of Regular expressions
  2. line 4 uses Matcher, the core of Regular expressions
  3. line 5 uses find, the core of Regular expressions
Read the full explanation (about 2 min)

A regular expression describes a pattern of text. In Java you compile it into a Pattern, run it against text with a Matcher, and read what matched. String.matches and replaceAll are shortcuts for one-off use.

A mental model

A stencil with holes: you slide it over text and it lights up everything that fits, such as "three digits, a dash, four digits".

How it works

Pattern p = Pattern.compile("(\\d{3})-(\\d{4})"); Matcher m = p.matcher(text); builds the pattern once. m.find() looks for the next match; m.group(1) reads a captured part.

matches() requires the whole string to match; find() looks for a match anywhere; lookingAt() anchors at the start.

Backslashes must be doubled in Java string literals: the regex \\d is written "\\d". Text blocks and raw patterns make this easier to read.

String.replaceAll(regex, replacement) and split(regex) take a regex, not plain text; special characters such as . and + must be escaped, or use Pattern.quote.

Going deeper

Compile patterns once and keep them in a static final field. String.matches and replaceAll recompile on every call, which is slow in a loop.

Some patterns take exponential time on certain inputs (catastrophic backtracking), for example nested quantifiers like (a+)+$. On user-supplied text this is a denial-of-service risk; keep patterns simple and bound the input length.

Regex is the wrong tool for nested structures such as HTML, JSON or code. Use a parser for those.

Name your groups ((?<year>\\d{4})) and read them with m.group("year") so the code survives a change to the pattern.

Under the hood

Java's engine compiles the pattern into a graph of nodes and matches by backtracking: on failure it returns to the last choice point and tries another path. That is simple and powerful, and also the reason bad patterns can blow up.

Common mistakes

  • Forgetting to double backslashes.
  • Compiling a pattern inside a loop.
  • Using matches when find is meant (it needs the whole string).
  • Splitting on . or | without escaping.
  • Running an unbounded pattern on untrusted input.

How Unravel recognises it

When you paste code, Unravel looks for these signs of regular expressions. Spotting them yourself is a good habit when you read unfamiliar code:

Part of a learning path

Related concepts

Frequently asked questions

What is Regular expressions?

A regular expression describes a pattern of text. In Java you compile it into a Pattern, run it against text with a Matcher, and read what matched. String.matches and replaceAll are shortcuts for one-off use.

What are the most common mistakes with Regular expressions?

Forgetting to double backslashes. Compiling a pattern inside a loop. Using matches when find is meant (it needs the whole string). Splitting on . or | without escaping. Running an unbounded pattern on untrusted input.

How can I see Regular expressions in real code?

Paste your own Java into Unravel and it will point out where regular expressions appears, explain how it works at the detail level you choose, and draw the flow of the code around it.