A regex (regular expression) is a single string used to represent another string or a set of particular strings.
| Syntax | Description | Example Matches |
|---|---|---|
. |
any single character except a newline (\n) |
c.t matches "cat", "cut", "c*t" |
\d |
any digit (0–9) |
\d{2} matches "42" |
\D |
any non-digit character | \D matches "A", "$" |
\w |
any word character (letters, digits, underscore) | \w+ matches "user_name1" |
\W |
any non-word character (spaces, punctuation, symbols) | \W matches "!", " " |
\s |
any whitespace character (spaces, tabs, newlines) | \s matches a tab or space |
\S |
any non-whitespace character | \S matches visible text characters |
| Syntax | Description | Example |
|---|---|---|
^ |
start of a string (or line, in multiline mode) | ^Hello matches strings beginning with "Hello" |
$ |
end of a string (or line) | [0-9]$ matches strings ending with a digit |
\b |
word boundary (between a \w and a \W char) |
\bcat\b matches "cat" but not "caterpillar" |
\B |
non-word boundary | \Bcat\B matches "location" (inside "cat") |
| Syntax | Description | Example |
|---|---|---|
* |
0 or more times | a* matches "", "a", "aaa" |
+ |
1 or more times | \d+ matches "5", "1234" |
? |
0 or 1 time (optional) | colou?r matches "color" or "colour" |
{n} |
exactly n times | \d{3} matches exactly 3 digits |
{n,} |
n or more times | \w{5,} matches words with 5+ characters |
{n,m} |
between n and m times | [a-z]{2,4} matches 2 to 4 lowercase letters |
*?, +? |
lazy modifier — appending ? to a quantifier makes it match as few characters as possible instead of as many |
".*?" matches text inside quotes minimally |
Quantifier examples:
a?b 0 or 1 occurrence of preceding element → ab or b
a*b 0 or more occurrence of preceding element → b, ab, aab
a+b 1 or more occurrence of preceding element → ab, aab
| Syntax | Description | Example |
|---|---|---|
[abc] |
any single character listed inside the brackets | [aeiou] matches any lowercase vowel |
[^abc] |
negated set — anything except the listed characters | [^0-9] matches any non-digit character |
[a-z] |
any character within the specified range | [A-Z] matches any uppercase English letter |
| Syntax | Description | Example |
|---|---|---|
(...) |
capturing group — groups items and captures the matched text into a numbered index | (\d{3})-(\d{2}) |
(?:...) |
non-capturing group — groups items without saving the match into memory | (?:un)?do |
| |
alternation — acts as "OR" | li(k|f)e matches "like" or "life" |
\1, \2 |
backreference — refers back to text matched by a previous capturing group | (\b\w+\b)\s+\1 matches duplicate adjacent words |
Lookarounds check text ahead or behind the current position without consuming characters into the match.
| Syntax | Description | Example |
|---|---|---|
(?=...) |
positive lookahead — pattern must follow immediately | \d(?=px) matches digits only if followed by "px" |
(?!...) |
negative lookahead — pattern must not follow immediately | \d(?!px) matches digits not followed by "px" |
(?<=...) |
positive lookbehind — pattern must precede immediately | (?<=\$)\d+ matches numbers preceded by a dollar sign |
(?<!...) |
negative lookbehind — pattern must not precede immediately | (?<!\$)\d+ matches numbers not preceded by a dollar sign |
To treat a reserved regex metacharacter (. * ? ^ $ ( ) [ ] { } \ | /) as a literal character, escape it with a backslash.
\. \* \\ escaped special characters
\t \n \r tab, linefeed, carriage return
Example: \. matches a literal dot instead of acting as a wildcard.
| Piece | Role |
|---|---|
Pattern |
the rule |
Matcher |
the worker that applies the rule |
| String | what gets searched |
Pattern p = Pattern.compile("\\d+");This builds a rule for "one or more digits." p just holds the rule , nothing is searched yet.
Matcher m = p.matcher("order 42, item 7");This says: apply that rule to this string. m is now ready to search.
while (m.find()) {
System.out.println(m.group());
}m.find(): searches from where it last stopped; if it finds a match, returnstrueand stores it.m.group(): returns what was just found (doesn't search on its own).
| Call | What happens | m.group() |
|---|---|---|
1st find() |
scans from position 0, finds "42" | "42" |
2nd find() |
scans from right after "42", finds "7" | "7" |
3rd find() |
scans to end, finds nothing | loop exits |
Matcher m = p.matcher("order 42");
m.group(); // CRASH , no find() called yet
m.find(); // now it searches and stores "42"
m.group(); // works , returns "42"group() only reads the last successful match , it never searches on its own.
When the pattern has (parentheses), each pair is a numbered capture. group(0) (or plain group()) is always the whole match. group(1) is the first (...), group(2) the second, etc.
Pattern p = Pattern.compile("(\\w+)@(\\w+)\\.com");
Matcher m = p.matcher("stitch@example.com");
m.matches(); // run the match first , returns true/false
m.group(0); // "stitch@example.com" → whole match
m.group(1); // "stitch" → 1st parens
m.group(2); // "example" → 2nd parensThink of (...) as "and also remember this specific piece separately."
m.matches(): tries to fit the pattern against the entire string, start to end, once. Returnstrue/false; iftrue, stores that whole-string match sogroup()works after.m.find(): tries to fit the pattern anywhere inside the string, can be called repeatedly to walk forward through multiple matches.
String log = "TXN acc-1042 sent to acc-2087, fee acc-9001";
Pattern p = Pattern.compile("acc-\\d{4}");
Matcher m = p.matcher(log);
while (m.find()) {
System.out.println(m.group());
}Output:
acc-1042
acc-2087
acc-9001
const regex = /meow/g;
const text = "meow is crazy meow meow";
console.log(text.replace(regex, "MEEW"));Output:
MEEW is crazy MEEW MEEW
Basic regex symbols used here:
| Regex | Meaning |
|---|---|
< |
match literal < |
> |
match literal > |
. |
any character |
+ |
one or more of the previous thing |
[...] |
character set |
[^...] |
NOT these characters |
(...) |
capturing group |
\1 |
match the same text captured by group 1 |
The regex:
<([A-Za-z0-9 ]+)>([^<>]+)</\1>
Think of it as: <tag>content</tag>
Breakdown:
<→ opening<([A-Za-z0-9 ]+)→ group 1: tag name>→ closing>([^<>]+)→ group 2: content (cannot contain<or>)</→ closing tag starts\1→ same tag name as group 1>→ closing>
For <h1>Hello World</h1>:
m.group(1) → "h1"
m.group(2) → "Hello World"
m.group() → "<h1>Hello World</h1>" — the entire match
In Java, \\1 in a string literal represents the regex \1. It means: "match exactly what group 1 matched."
<h1>Hello</h1> ✅ — closing tag is h1, matches group 1
<h1>Hello</h2> ❌ — closing tag is h2, group 1 was h1, no match
[^<>]+ means: one or more characters that are NOT < or >. This prevents nested tags from being treated as valid outer content.
<h1>Hello</h1> → "Hello" ✅
<h1><a>Hello</a></h1> → outer content invalid; inner "Hello" is valid
Regex \1 becomes the Java string "\\1", because Java uses \ as its own escape character first.
Capturing group + backreference = a way to check that two parts of a string are identical:
(...)→ capture something\1→ require the same thing again This pattern (matching opening/closing tags, or detecting duplicated text) is the core use case for backreferences.
1. Core mental model (Pattern, Matcher, String)
Pattern p = Pattern.compile("regex");— compiles the rule into memoryMatcher m = p.matcher(text);— applies that rule to a specific stringm.find()/m.matches()— search for the pattern (findscans anywhere;matcheschecks the entire string start to finish) 2. Character classes & quantifiers[a-zA-Z]— a character set matching any single letter\w— any word character (letters, digits, underscore){7,29}— a quantifier specifying a range (between 7 and 29 repetitions). Always use commas inside curly braces, not hyphens.[^>]— a negated set meaning "any character except>" 3. Anchors^— asserts the start of a string$— asserts the end of a string 4. Groups & backreferences(...)(capturing groups) — captures matched text into numbered slotsm.group(0)= the whole matchm.group(1),m.group(2)= specific parenthesized pieces
\1(backreference) — reuses text captured by the first group. Essential for validating matching opening/closing HTML/XML tags (e.g. ensuring<(.+)>matches its corresponding</\1>)