Regular Expressions

A regular expression (regex) is a pattern that describes text: "an email address", "a date like 2026-03-05", "one or more digits". Java's java.util.regex package uses patterns to validate input, search text, extract parts and perform smart replacements.

Matching a whole string

JAVA
public class Main {
    public static void main(String[] args) {
        System.out.println("2026-03-05".matches("\\d{4}-\\d{2}-\\d{2}"));
        System.out.println("5 March".matches("\\d{4}-\\d{2}-\\d{2}"));
        System.out.println("AB-12-CD".matches("[A-Z]{2}-\\d{2}-[A-Z]{2}"));
    }
}
Output
true
false
true

String.matches checks whether the entire string fits the pattern. In Java string literals, a regex backslash must be written twice: the regex \d (a digit) is "\\d" in code.

Pattern building blocks

PatternMatches
.Any character
\d, \w, \sDigit, word character (letter/digit/_), whitespace
\D, \W, \SThe opposites
[abc], [a-z], [^0-9]One of, a range, none of
*, +, ?0 or more, 1 or more, 0 or 1
{3}, {2,5}Exactly 3, between 2 and 5
^, $Start and end of input (or line)
(…), (?<name>…)A capturing group, a named group
a|bEither
\bWord boundary

Finding matches

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

public class Main {
    public static void main(String[] args) {
        String text = "Order A-17 shipped, order B-204 pending, order C-9 cancelled.";
        Pattern orderId = Pattern.compile("[A-Z]-\\d+");
        Matcher m = orderId.matcher(text);
        while (m.find()) {
            System.out.println(m.group() + " at " + m.start());
        }
        System.out.println(orderId.matcher(text).results().count() + " orders");
    }
}
Output
A-17 at 6
B-204 at 26
C-9 at 47
3 orders

Compile a Pattern once (it's reusable and thread-safe), then use a Matcher to find each occurrence. results() streams all matches.

Capturing groups

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

public class Main {
    public static void main(String[] args) {
        Pattern logLine = Pattern.compile("(?<date>\\d{4}-\\d{2}-\\d{2}) (?<level>INFO|WARN|ERROR) (?<msg>.+)");
        String[] lines = {
            "2026-03-05 ERROR Disk almost full",
            "2026-03-05 INFO Backup complete",
            "not a log line"
        };
        for (String line : lines) {
            Matcher m = logLine.matcher(line);
            if (m.matches()) {
                System.out.println(m.group("level") + " on " + m.group("date") + ": " + m.group("msg"));
            } else {
                System.out.println("Skipped: " + line);
            }
        }
    }
}
Output
ERROR on 2026-03-05: Disk almost full
INFO on 2026-03-05: Backup complete
Skipped: not a log line

Parentheses capture parts of a match. Named groups ((?<level>…)) make extraction readable.

Replacing and splitting

JAVA
public class Main {
    public static void main(String[] args) {
        System.out.println("Call 912 345 678 or 213-456-789".replaceAll("\\d", "#"));
        System.out.println("too    many     spaces".replaceAll("\\s+", " "));
        System.out.println("2026-03-05".replaceAll("(\\d{4})-(\\d{2})-(\\d{2})", "$3/$2/$1"));
        System.out.println(String.join("|", "a, b;c ,  d".split("\\s*[,;]\\s*")));
    }
}
Output
Call ### ### ### or ###-###-###
too many spaces
05/03/2026
a|b|c|d

In replacements, $1, $2… insert captured groups. split also takes a regex, which is handy for messy separators.

Flags and escaping

JAVA
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        Pattern p = Pattern.compile("^error:", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
        System.out.println(p.matcher("ok\nERROR: x\nError: y").results().count());

        String price = "Price: $9.99";
        System.out.println(price.matches(".*\\$9\\.99"));
        System.out.println(price.matches(".*" + Pattern.quote("$9.99")));
    }
}
Output
2
true
true

Characters like . $ ^ * + ? ( ) [ ] { } | \ have special meanings; escape them with a backslash, or wrap user-supplied text in Pattern.quote.

Use regex wisely

Regular expressions are excellent for well-defined formats, but complex ones become unreadable — comment them or split them up. Don't use regex to parse HTML, JSON or full email address rules; use proper parsers and libraries.

Try it yourself

Extract all hashtags from a post, lower-cased and without duplicates.

Try it yourself · Main.java
Edit the code, copy it into Main.java and run java Main.java (Java 25+). How to set up Java
Output
[java, records, streams, codeatlas]