Regular expression basics
A summary of the syntax, and the one thing about Java's version that trips everyone.
The escaping problem
A regex lives in a Java string, so backslashes are consumed twice — once by the compiler, once by the regex engine. A regex \d must be written "\\d":
"1.2.3".split("\\.") // literal dot
Pattern.compile("\\d+") // one or more digits
This is the single most common source of confusion, and the error message rarely says so. If a pattern behaves oddly, check the backslashes before anything else.
Character classes
| Pattern | Matches |
|---|---|
. |
any character except a newline |
\d |
a digit |
\D |
not a digit |
\w |
word character: letter, digit or underscore |
\s |
whitespace |
[abc] |
a, b or c |
[^abc] |
anything but those |
[a-z] |
a range |
Quantifiers
| Pattern | Meaning |
|---|---|
* |
zero or more |
+ |
one or more |
? |
zero or one |
{n} |
exactly n |
{n,} |
n or more |
{n,m} |
between n and m |
These are greedy: they take as much as possible and give back only if the match fails. Adding ? makes them reluctant, which is the fix for the classic problem of <.*> swallowing an entire line of HTML where <.*?> matches one tag.
Anchors and groups
^ start, $ end, \b word boundary. Parentheses group and capture; (?:...) groups without capturing.
Pattern p = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher m = p.matcher("2026-08-28");
if (m.matches()) {
String year = m.group(1);
}
Group 0 is the whole match; groups count from 1, left to right by opening parenthesis.
matches, find, lookingAt
matches() requires the entire string to match. find() looks for a match anywhere. Confusing the two accounts for most “my regex works in a tester but not in Java” reports — online testers usually behave like find.
String.matches is whole-string too:
"abc123".matches("\\d+") // false
Pattern.compile("\\d+").matcher("abc123").find() // true
Compile once
String.matches recompiles the pattern on every call. In a loop, hoist it:
private static final Pattern DIGITS = Pattern.compile("\\d+");
When not to
Regexes are poor at nested structure. Do not parse HTML, XML or JSON with one — use a parser. And a regex that needs a comment to be readable usually wants to be a small method instead.