When validating user input or searching for patterns in text, regular expressions provide a compact language for matching. Regex fundamentals help you write validation, search, extraction, and replacement logic.

Literal Matching

Literal.java
// Literal matching

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

public class Literal {

    public static void main(String[] args) {
        // Literal match
        String text1 = ;
        boolean matches1 = text1.matches("hello");
        System.out.println("'hello' matches 'hello': " + matches1);

        boolean matches2 = text1.matches("world");
        System.out.println("'hello' matches 'world': " + matches2);

        // Pattern and Matcher
        Pattern pattern = Pattern.compile("hello");
        Matcher matcher1 = pattern.matcher("hello");
        System.out.println("\nMatcher matches: " + matcher1.matches());

        Matcher matcher2 = pattern.matcher("hello world");
        System.out.println("Matcher matches 'hello world': " + matcher2.matches());

        // Find pattern (doesn't require full match)
        Matcher matcher3 = pattern.matcher("hello world");
        System.out.println("Find 'hello' in 'hello world': " + matcher3.find());

        // Case sensitivity
        boolean matches3 = "Hello".matches("hello");
        System.out.println("\n'Hello' matches 'hello': " + matches3);

        // Case insensitive
        Pattern caseInsensitive = Pattern.compile("hello", Pattern.CASE_INSENSITIVE);
        Matcher matcher4 = caseInsensitive.matcher("Hello");
        System.out.println("Case insensitive match: " + matcher4.matches());

        // Multiple occurrences
        String text2 = "hello hello hello";
        Matcher matcher5 = pattern.matcher(text2);

        System.out.println("\nFind all occurrences:");
        while (matcher5.find()) {
            System.out.println("  Found at index: " + matcher5.start());
        }
    }

}
// Literal matching

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

public class Literal {

    public static void main(String[] args) {
        // Literal match
        String text1 = ;
        boolean matches1 = text1.matches("hello");
        System.out.println("'hello' matches 'hello': " + matches1);

        boolean matches2 = text1.matches("world");
        System.out.println("'hello' matches 'world': " + matches2);

        // Pattern and Matcher
        Pattern pattern = Pattern.compile("hello");
        Matcher matcher1 = pattern.matcher("hello");
        System.out.println("\nMatcher matches: " + matcher1.matches());

        Matcher matcher2 = pattern.matcher("hello world");
        System.out.println("Matcher matches 'hello world': " + matcher2.matches());

        // Find pattern (doesn't require full match)
        Matcher matcher3 = pattern.matcher("hello world");
        System.out.println("Find 'hello' in 'hello world': " + matcher3.find());

        // Case sensitivity
        boolean matches3 = "Hello".matches("hello");
        System.out.println("\n'Hello' matches 'hello': " + matches3);

        // Case insensitive
        Pattern caseInsensitive = Pattern.compile("hello", Pattern.CASE_INSENSITIVE);
        Matcher matcher4 = caseInsensitive.matcher("Hello");
        System.out.println("Case insensitive match: " + matcher4.matches());

        // Multiple occurrences
        String text2 = "hello hello hello";
        Matcher matcher5 = pattern.matcher(text2);

        System.out.println("\nFind all occurrences:");
        while (matcher5.find()) {
            System.out.println("  Found at index: " + matcher5.start());
        }
    }

}
pattern A string that defines search criteria. It can include literal characters and special metacharacters.

Character Classes

CharacterClass.java
// Character classes

import java.util.regex.Pattern;

public class CharacterClass {

    public static void main(String[] args) {
        // Match one of specific characters
        System.out.println("a".matches("[abc]"));  // true
        System.out.println("b".matches("[abc]"));  // true
        System.out.println("d".matches("[abc]"));  // false

        // Range
        System.out.println("\nRanges:");
        System.out.println("5".matches("[0-9]"));  // true - digit
        System.out.println("m".matches("[a-z]"));  // true - lowercase
        System.out.println("M".matches("[A-Z]"));  // true - uppercase
        System.out.println("M".matches("[a-z]"));  // false

        // Multiple ranges
        System.out.println("\nMultiple ranges:");
        System.out.println("a".matches("[a-zA-Z]"));  // true - any letter
        System.out.println("5".matches("[a-zA-Z]"));  // false
        System.out.println("5".matches("[a-zA-Z0-9]"));  // true - alphanumeric

        // Negation [^...]
        System.out.println("\nNegation:");
        System.out.println("a".matches("[^0-9]"));  // true - not a digit
        System.out.println("5".matches("[^0-9]"));  // false - is a digit

        // Predefined character classes
        System.out.println("\nPredefined classes:");
        System.out.println("5".matches("\\d"));    // digit
        System.out.println("a".matches("\\d"));    // false
        System.out.println("a".matches("\\w"));    // word char
        System.out.println(" ".matches("\\s"));    // whitespace
        System.out.println("a".matches("\\D"));    // non-digit
        System.out.println("5".matches("\\D"));    // false

        // Dot . matches any character
        System.out.println("\nDot (any char):");
        System.out.println("a".matches("."));      // true
        System.out.println("5".matches("."));      // true
        System.out.println(" ".matches("."));      // true
    }

}
character_class Square brackets such as [abc] match any single character from a set. Ranges such as [a-z] match a span of characters.

Quantifiers

Quantifiers.java
// Quantifiers

public class Quantifiers {

    public static void main(String[] args) {
        // * (0 or more)
        System.out.println("Asterisk * (0 or more):");
        System.out.println("".matches("a*"));      // true - 0 a's
        System.out.println("a".matches("a*"));     // true - 1 a
        System.out.println("aaa".matches("a*"));   // true - 3 a's
        System.out.println("b".matches("a*"));     // false - not a

        // + (1 or more)
        System.out.println("\nPlus + (1 or more):");
        System.out.println("".matches("a+"));      // false - 0 a's
        System.out.println("a".matches("a+"));     // true - 1 a
        System.out.println("aaa".matches("a+"));   // true - 3 a's

        // ? (0 or 1)
        System.out.println("\nQuestion ? (0 or 1):");
        System.out.println("".matches("a?"));      // true - 0 a's
        System.out.println("a".matches("a?"));     // true - 1 a
        System.out.println("aa".matches("a?"));    // false - 2 a's

        // {n} (exactly n)
        System.out.println("\n{n} (exactly n):");
        System.out.println("aa".matches("a{2}"));  // true
        System.out.println("aaa".matches("a{2}")); // false
        System.out.println("a".matches("a{2}"));   // false

        // {n,} (n or more)
        System.out.println("\n{n,} (n or more):");
        System.out.println("aa".matches("a{2,}"));    // true - 2 a's
        System.out.println("aaa".matches("a{2,}"));   // true - 3 a's
        System.out.println("a".matches("a{2,}"));     // false - only 1

        // {n,m} (between n and m)
        System.out.println("\n{n,m} (between n and m):");
        System.out.println("aa".matches("a{2,4}"));   // true
        System.out.println("aaa".matches("a{2,4}"));  // true
        System.out.println("aaaa".matches("a{2,4}")); // true
        System.out.println("a".matches("a{2,4}"));    // false - too few
        System.out.println("aaaaa".matches("a{2,4}")); // false - too many

        // Practical: digits
        System.out.println("\nPractical - validate numbers:");
        System.out.println("123".matches("\\d+"));      // true - one or more digits
        System.out.println("12345".matches("\\d{5}"));  // true - exactly 5 digits
        System.out.println("123".matches("\\d{2,4}"));  // true - 2-4 digits
    }

}
quantifier A symbol that specifies how many times the preceding element should match, such as *, +, ?, or {n}.

Anchors

Anchors.java
// Anchors

public class Anchors {

    public static void main(String[] args) {
        // ^ (start of string)
        System.out.println("Start anchor ^:");
        System.out.println("hello".matches("^hello"));       // true
        System.out.println("hello world".matches("^hello")); // false - matches() requires full match
        System.out.println("world hello".matches("^hello")); // false

        // For partial matching, use find()
        System.out.println("\nUsing find() with ^:");
        System.out.println("hello world".matches("hello.*"));  // true - starts with hello
        System.out.println("world hello".matches("hello.*"));  // false

        // $ (end of string)
        System.out.println("\nEnd anchor $:");
        System.out.println("hello".matches(".*hello$"));     // true
        System.out.println("hello world".matches(".*world$")); // true
        System.out.println("world hello".matches(".*world$")); // false

        // Both anchors
        System.out.println("\nBoth anchors ^...$:");
        System.out.println("hello".matches("^hello$"));      // true - exact match
        System.out.println("hello world".matches("^hello$")); // false

        // \b (word boundary)
        System.out.println("\nWord boundary \\b:");
        String text = "hello world";
        System.out.println(text.matches(".*\\bhello\\b.*"));   // true - hello as word
        System.out.println(text.matches(".*\\bworld\\b.*"));   // true - world as word
        System.out.println("helloworld".matches(".*\\bhello\\b.*")); // false - no boundary

        // Practical examples
        System.out.println("\nPractical validation:");

        // Must start with letter
        System.out.println("abc123".matches("^[a-zA-Z].*"));  // true
        System.out.println("123abc".matches("^[a-zA-Z].*"));  // false

        // Must end with digit
        System.out.println("abc123".matches(".*\\d$"));       // true
        System.out.println("abc".matches(".*\\d$"));          // false

        // Exact length
        System.out.println("12345".matches("^\\d{5}$"));      // true - exactly 5 digits
        System.out.println("1234".matches("^\\d{5}$"));       // false
    }

}
anchor An anchor matches a position rather than a character, such as start of string, end of string, or a word boundary.

Groups

Groups.java
// Groups and capturing

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

public class Groups {

    public static void main(String[] args) {
        // Basic grouping
        String date = ;
        Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
        Matcher matcher = pattern.matcher(date);

        if (matcher.matches()) {
            System.out.println("Full match: " + matcher.group(0));
            System.out.println("Year: " + matcher.group(1));
            System.out.println("Month: " + matcher.group(2));
            System.out.println("Day: " + matcher.group(3));
        }

        // Email parsing
        String email = "user@example.com";
        Pattern emailPattern = Pattern.compile("([^@]+)@([^@]+)");
        Matcher emailMatcher = emailPattern.matcher(email);

        if (emailMatcher.matches()) {
            System.out.println("\nEmail parts:");
            System.out.println("Username: " + emailMatcher.group(1));
            System.out.println("Domain: " + emailMatcher.group(2));
        }

        // Phone number
        String phone = "(555) 123-4567";
        Pattern phonePattern = Pattern.compile("\\((\\d{3})\\)\\s(\\d{3})-(\\d{4})");
        Matcher phoneMatcher = phonePattern.matcher(phone);

        if (phoneMatcher.matches()) {
            System.out.println("\nPhone parts:");
            System.out.println("Area: " + phoneMatcher.group(1));
            System.out.println("Exchange: " + phoneMatcher.group(2));
            System.out.println("Number: " + phoneMatcher.group(3));
        }

        // Multiple matches
        String text = "Call me at 555-1234 or 555-5678";
        Pattern numPattern = Pattern.compile("(\\d{3})-(\\d{4})");
        Matcher numMatcher = numPattern.matcher(text);

        System.out.println("\nAll phone numbers:");
        while (numMatcher.find()) {
            System.out.println("  " + numMatcher.group(0) + 
                             " (Area: " + numMatcher.group(1) + 
                             ", Num: " + numMatcher.group(2) + ")");
        }

        // Non-capturing group (?:...)
        String url = "https://example.com";
        Pattern urlPattern = Pattern.compile("(https?)://(.+)");
        Matcher urlMatcher = urlPattern.matcher(url);

        if (urlMatcher.matches()) {
            System.out.println("\nURL parts:");
            System.out.println("Protocol: " + urlMatcher.group(1));
            System.out.println("Domain: " + urlMatcher.group(2));
        }
    }

}
// Groups and capturing

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

public class Groups {

    public static void main(String[] args) {
        // Basic grouping
        String date = ;
        Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
        Matcher matcher = pattern.matcher(date);

        if (matcher.matches()) {
            System.out.println("Full match: " + matcher.group(0));
            System.out.println("Year: " + matcher.group(1));
            System.out.println("Month: " + matcher.group(2));
            System.out.println("Day: " + matcher.group(3));
        }

        // Email parsing
        String email = "user@example.com";
        Pattern emailPattern = Pattern.compile("([^@]+)@([^@]+)");
        Matcher emailMatcher = emailPattern.matcher(email);

        if (emailMatcher.matches()) {
            System.out.println("\nEmail parts:");
            System.out.println("Username: " + emailMatcher.group(1));
            System.out.println("Domain: " + emailMatcher.group(2));
        }

        // Phone number
        String phone = "(555) 123-4567";
        Pattern phonePattern = Pattern.compile("\\((\\d{3})\\)\\s(\\d{3})-(\\d{4})");
        Matcher phoneMatcher = phonePattern.matcher(phone);

        if (phoneMatcher.matches()) {
            System.out.println("\nPhone parts:");
            System.out.println("Area: " + phoneMatcher.group(1));
            System.out.println("Exchange: " + phoneMatcher.group(2));
            System.out.println("Number: " + phoneMatcher.group(3));
        }

        // Multiple matches
        String text = "Call me at 555-1234 or 555-5678";
        Pattern numPattern = Pattern.compile("(\\d{3})-(\\d{4})");
        Matcher numMatcher = numPattern.matcher(text);

        System.out.println("\nAll phone numbers:");
        while (numMatcher.find()) {
            System.out.println("  " + numMatcher.group(0) + 
                             " (Area: " + numMatcher.group(1) + 
                             ", Num: " + numMatcher.group(2) + ")");
        }

        // Non-capturing group (?:...)
        String url = "https://example.com";
        Pattern urlPattern = Pattern.compile("(https?)://(.+)");
        Matcher urlMatcher = urlPattern.matcher(url);

        if (urlMatcher.matches()) {
            System.out.println("\nURL parts:");
            System.out.println("Protocol: " + urlMatcher.group(1));
            System.out.println("Domain: " + urlMatcher.group(2));
        }
    }

}
capturing_group Parentheses group parts of a pattern and capture matched text for extraction.

Practical Validation

Regex patterns are often used to validate usernames, emails, phone numbers, passwords, URLs, and dates.

Practical.java
// Practical validation

import java.util.regex.Pattern;

public class Practical {

    public static boolean isValidUsername(String username) {
        // 3-16 chars, alphanumeric and underscore, must start with letter
        return username.matches("^[a-zA-Z][a-zA-Z0-9_]{2,15}$");
    }

    public static boolean isValidEmail(String email) {
        // Basic email pattern
        return email.matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");
    }

    public static boolean isValidPhone(String phone) {
        // Format: (123) 456-7890 or 123-456-7890
        return phone.matches("^(\\(\\d{3}\\)\\s?|\\d{3}-)\\d{3}-\\d{4}$");
    }

    public static boolean isStrongPassword(String password) {
        // At least 8 chars, with uppercase, lowercase, and digit
        boolean hasLength = password.length() >= 8;
        boolean hasUpper = password.matches(".*[A-Z].*");
        boolean hasLower = password.matches(".*[a-z].*");
        boolean hasDigit = password.matches(".*\\d.*");

        return hasLength && hasUpper && hasLower && hasDigit;
    }

    public static boolean isValidURL(String url) {
        return url.matches("^https?://[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}.*$");
    }

    public static boolean isValidDate(String date) {
        return date.matches("^\\d{4}-\\d{2}-\\d{2}$");
    }

    public static void main(String[] args) {
        // Usernames
        String[] usernames = {"alice", "bob123", "a", "user_name", "123user"};
        System.out.println("Usernames:");
        for (String user : usernames) {
            System.out.println("  " + user + ": " + isValidUsername(user));
        }

        // Emails
        String[] emails = {"user@example.com", "invalid", "test@test.co.uk"};
        System.out.println("\nEmails:");
        for (String email : emails) {
            System.out.println("  " + email + ": " + isValidEmail(email));
        }

        // Phones
        String[] phones = {"(555) 123-4567", "555-123-4567", "5551234567"};
        System.out.println("\nPhones:");
        for (String phone : phones) {
            System.out.println("  " + phone + ": " + isValidPhone(phone));
        }

        // Passwords
        String[] passwords = {"weak", "Strong123", "nodigits", "NOCAPS123"};
        System.out.println("\nPasswords:");
        for (String pwd : passwords) {
            System.out.println("  " + pwd + ": " + isStrongPassword(pwd));
        }

        // URLs
        String[] urls = {"https://example.com", "http://test.org/path", "invalid"};
        System.out.println("\nURLs:");
        for (String url : urls) {
            System.out.println("  " + url + ": " + isValidURL(url));
        }

        // Dates
        String[] dates = {"2025-01-29", "2025-1-9", "01/29/2025"};
        System.out.println("\nDates:");
        for (String date : dates) {
            System.out.println("  " + date + ": " + isValidDate(date));
        }
    }

}

Exercise: Practical.java

Validate that a username contains only letters, numbers, and underscores, and is 3-16 characters long