Las expresiones regulares de Java viven en java.util.regex y tienen dos particularidades que no están en otros lenguajes: la barra invertida hay que duplicarla, y por omisión \w no reconoce los acentos.
También te puede interesar
La doble barra
"2026-10-08".matches("\\d{4}-\\d{2}-\\d{2}")salidatrue
\d4; lo que pasa es que en una cadena de Java \ ya significa algo, así que hay que escribirla dos veces para que llegue una. Es el motivo del 90 % de los «no me funciona la regex» al venir de otro lenguaje. Desde Java 15 puedes usar un bloque de texto para escribirla tal cual.Buscar todas las coincidencias
Pattern p = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher m = p.matcher("la fecha 2026-10-08 y la 2025-01-31");
while (m.find()) {
System.out.println(" " + m.group() + " -> año " + m.group(1)
+ ", mes " + m.group(2) + " en la posición " + m.start());
}salida2026-10-08 -> año 2026, mes 10 en la posición 9 2025-01-31 -> año 2025, mes 01 en la posición 25
matches exige que toda la cadena encaje; find busca un trozo y se puede llamar en bucle. Confundirlos es el segundo error clásico. group(0) —o group()— es lo que encajó entero y del 1 en adelante van los paréntesis, de izquierda a derecha.
String.matches compila la expresión en cada llamada. Dentro de un bucle, saca el Pattern.compile fuera y guárdalo en una constante static final: es la optimización más rentable de esta página.Grupos con nombre
Matcher mc = Pattern.compile("(?<anio>\\d{4})-(?<mes>\\d{2})").matcher("2026-10");
if (mc.matches()) {
System.out.println("anio=" + mc.group("anio") + " mes=" + mc.group("mes"));
}salidaanio=2026 mes=10
Mucho mejor que contar paréntesis, sobre todo cuando mañana alguien añada uno en medio. Pero cuidado con el nombre:
Pattern.compile("(?<año>\\d{4})");salidaPatternSyntaxException: named capturing group is missing trailing '>'
Los nombres de grupo en Java solo admiten letras del inglés y dígitos, y tienen que empezar por letra. Nada de eñes ni de acentos, y el mensaje de error no lo dice: se limita a quejarse de que falta el >.
Reemplazar y partir
System.out.println("uno, dos,tres".replaceAll("\\s*,\\s*", " | "));
System.out.println(Arrays.toString("a1b22c333d".split("\\d+")));salidauno | dos | tres [a, b, c, d]
En el reemplazo, $1 mete lo que capturó el primer grupo. Y si el texto de reemplazo viene de fuera, Matcher.quoteReplacement evita que un $ suelto lo rompa.
Las banderas, y la de los acentos
System.out.println(Pattern.compile("hola", Pattern.CASE_INSENSITIVE)
.matcher("HOLA mundo").find());
System.out.println("añil".matches("\\w+"));
System.out.println(Pattern.compile("\\w+", Pattern.UNICODE_CHARACTER_CLASS)
.matcher("añil").matches());salidatrue false true
false es importante si escribes en español. Por omisión, \w en Java significa [a-zA-Z0-9_] y deja fuera la eñe y los acentos; lo mismo le pasa a \b y a \s con los espacios raros. Se arregla con UNICODE_CHARACTER_CLASS, o escribiendo (?U) al principio del patrón. Un validador de nombres hecho con \w+ rechaza a cualquiera que se llame Muñoz.| Bandera | Qué hace |
|---|---|
CASE_INSENSITIVE | ignora mayúsculas (solo ASCII si no añades UNICODE_CASE) |
UNICODE_CHARACTER_CLASS | \w, \d y \s entienden Unicode |
MULTILINE | ^ y $ valen en cada línea |
DOTALL | el punto también encaja con el salto de línea |
COMMENTS | permite espacios y comentarios dentro del patrón |
Cuando el patrón está mal
salidaPatternSyntaxException: Unclosed group
PatternSyntaxException es unchecked: el compilador no te obliga a capturarla, así que un patrón mal escrito que venga de un archivo de configuración revienta en ejecución. Si la expresión no es una constante tuya, compílala dentro de un try.
Más información en inglés: Regular expressions in Java.
Todo el código se compiló y se ejecutó con Java 25 LTS en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.