W3docs

Sintaxis de Regex en Java

Sintaxis de expresiones regulares en Java: caracteres, clases, anclas, cuantificadores y construcciones especiales.

Una expresión regular es un pequeño lenguaje de patrones para describir texto. Java lo implementa en el paquete java.util.regex, y la sintaxis es el dialecto de estilo Perl compartido por la mayoría de los lenguajes modernos, con una particularidad específica de Java: cada barra invertida en un patrón debe duplicarse en un literal de cadena Java, porque el compilador consume una antes de que el motor de regex la vea. Este capítulo es una referencia a esa sintaxis: los bloques de construcción que se combinan para buscar coincidencias, buscar y validar texto.

Si eres nuevo en las expresiones regulares en Java, comienza con la Introducción a Regex en Java y vuelve aquí cuando necesites la hoja de referencia de sintaxis completa.

Literales y metacaracteres

La mayoría de los caracteres en un patrón se corresponden consigo mismos: cat coincide con las tres letras c, a, t. El poder proviene de los metacaracteres — caracteres con significado especial que combinas en reglas. Los doce que el motor trata de forma especial son:

. ^ $ * + ? ( ) [ ] { } | \

Para hacer coincidir uno de estos literalmente, escápalo con una barra invertida. Recuerda la regla de doble barra invertida en Java: un regex \. se escribe "\\." en el código.

Pattern.matches("a.c", "abc");   // true  — '.' matches any char
Pattern.matches("a.c", "a.c");   // true  — '.' also matches a literal dot
Pattern.matches("a\\.c", "abc"); // false — '\.' matches ONLY a literal dot
Pattern.matches("a\\.c", "a.c"); // true

Clases de caracteres

Una clase de caracteres entre corchetes hace coincidir cualquier un carácter de un conjunto. Los rangos usan un guión, y un ^ inicial niega el conjunto.

"[aeiou]"     // any one lowercase vowel
"[a-z]"       // any one lowercase letter
"[A-Za-z0-9]" // any letter or digit
"[^0-9]"      // any character that is NOT a digit

Java también ofrece clases predefinidas como abreviatura. Estas son las que se usan constantemente:

AbreviaturaEquivalenteCoincide con
.Cualquier carácter excepto un terminador de línea
\d[0-9]Un dígito
\D[^0-9]Un no dígito
\w[a-zA-Z0-9_]Un carácter de palabra
\W[^a-zA-Z0-9_]Un carácter de no palabra
\s[ \t\n\x0B\f\r]Un carácter de espacio en blanco
\S[^\s]Un carácter que no es espacio en blanco

La forma en mayúsculas siempre es la negación de la forma en minúsculas. Consulta Clases de Caracteres de Regex en Java para el conjunto completo, incluyendo las clases POSIX y Unicode.

Cuantificadores: ávidos, renuentes y posesivos

Un cuantificador indica cuántas veces puede repetirse el elemento anterior. Por defecto, los cuantificadores son ávidos — toman todo lo posible y luego retroceden si el resto del patrón lo necesita. Agrega ? para hacer un cuantificador renuente (coincidir con la mínima cantidad posible), o + para hacerlo posesivo (tomar y nunca ceder).

CuantificadorSignificado
*Cero o más
+Uno o más
?Cero o uno (opcional)
{n}Exactamente n
{n,}Al menos n
{n,m}Entre n y m
"\\d{3}"     // exactly three digits
"\\d{2,4}"   // two to four digits
"a+"         // one or more 'a'
"colou?r"    // matches "color" and "colour"
"<.+>"       // greedy:    on "<a><b>" matches the whole "<a><b>"
"<.+?>"      // reluctant: on "<a><b>" matches just "<a>"

Para un análisis más profundo del comportamiento ávido, renuente y posesivo, lee Cuantificadores de Regex en Java.

Anclas, límites y alternación

Las anclas coinciden con una posición, no con un carácter. ^ es el inicio de la entrada (o de la línea, en modo multilínea), $ es el final, y \b es un límite de palabra — el punto de ancho cero entre un \w y un \W. La alternación con | coincide con cualquiera de los lados.

"^Hello"      // "Hello" only at the start
"\\.txt$"     // ".txt" only at the end
"\\bcat\\b"   // "cat" as a whole word, not inside "category"
"cat|dog"     // "cat" or "dog"
"^(cat|dog)$" // the whole string is exactly "cat" or "dog"

Ten en cuenta que | tiene una precedencia muy baja: ^cat|dog$ significa (^cat)|(dog$), no ^(cat|dog)$. Envuelve las alternativas en un grupo cuando quieras que las anclas se apliquen a ambas.

Grupos, referencias anteriores e indicadores en línea

Los paréntesis crean un grupo de captura — el motor recuerda lo que coincidió en cada grupo, numerados de izquierda a derecha comenzando en 1. (?:...) es un grupo de no captura cuando solo necesitas aplicar un cuantificador. Una referencia anterior \1 coincide con el mismo texto que capturó el primer grupo. Los indicadores en línea como (?i) cambian el comportamiento de coincidencia sin un indicador separado en Pattern.compile.

"(\\d{4})-(\\d{2})"   // group 1 = year, group 2 = month
"(?:ab)+"             // repeats "ab" without capturing it
"(\\w+) \\1"          // a word followed by itself ("the the")
"(?i)java"            // case-insensitive: matches "Java", "JAVA"
"(?m)^line"           // multiline: ^ matches at each line start

Los grupos de captura tienen su propio capítulo — Grupos de Regex en Java cubre los grupos con nombre y cómo extraer el texto capturado de un Matcher. Los indicadores en línea como (?i) y (?m) son los equivalentes dentro del patrón de los indicadores de Pattern.compile descritos en Indicadores de Regex en Java.

Un ejemplo práctico: las construcciones en acción

Este programa ejercita una clase de dígitos con un cuantificador, alternación anclada, una referencia anterior, coincidencia ávida versus renuente, la abreviatura \w+ y un indicador de insensibilidad a mayúsculas en línea — todo contra java.util.regex únicamente. La sintaxis aquí impulsa la API de Pattern y Matcher cubierta en Pattern y Matcher de Regex en Java.

java— editable, runs on the server

Lo que se puede extraer de la ejecución:

  • \d{4} encontró tanto 1995 como 2011 porque find() busca cada coincidencia en la entrada, mientras que una clase más cuantificador (\d repetido {4} veces) es la forma canónica de hacer coincidir un campo de ancho fijo. La doble barra invertida en "\\d{4}" es el literal de cadena Java que produce la barra invertida simple que el motor espera.
  • Pattern.matches("cat|dog", "dog") devolvió true, pero el mismo patrón en "catnap" devolvió falsematches() ancla implícitamente la entrada completa, por lo que aunque cat aparece en catnap, el nap restante queda sin coincidir y la coincidencia general falla.
  • La referencia anterior \1 convirtió (\w+) \1 en "una palabra seguida de la misma palabra", por eso reportó the e is — las dos repeticiones — e ignoró cada palabra que no estaba inmediatamente repetida. Las referencias anteriores coinciden con el texto capturado, no con el patrón de nuevo.
  • En la misma entrada <a><b>, el ávido <.+> consumió toda la cadena mientras que el renuente <.+?> se detuvo en el primer >, produciendo solo <a>. Este único contraste es la corrección de errores de regex más común que harás: agrega ? a un cuantificador cuando toma demasiado.
  • \w+ contó 3 tokens en ab, cd-ef!ab, cd y ef — porque ,, - y ! son todos caracteres \W (de no palabra) que interrumpen una secuencia de caracteres de palabra. El indicador en línea (?i) entonces hizo coincidir java con JAVA, mostrando que los indicadores pueden vivir dentro del propio patrón en lugar de solo en Pattern.compile.

Práctica

Práctica
En la entrada '<a><b>', ¿por qué el regex '<.+>' coincide con toda la cadena '<a><b>' mientras que '<.+?>' solo coincide con '<a>'?
En la entrada '<a><b>', ¿por qué el regex '<.+>' coincide con toda la cadena '<a><b>' mientras que '<.+?>' solo coincide con '<a>'?
Was this page helpful?