JavaRush /Blog Java /Random-ES /Expresiones regulares en Java, parte 2

Expresiones regulares en Java, parte 2

Publicado en el grupo Random-ES
Presentamos a su atención una traducción de una breve guía sobre expresiones regulares en Java, escrita por Jeff Friesen para el sitio web javaworld . Para facilitar la lectura, hemos dividido el artículo en varias partes. Expresiones regulares en Java, Parte 2 - 1Expresiones regulares en Java, Parte 1
Fusionando múltiples rangos
Puede fusionar varios rangos en una única clase de caracteres de rango colocándolos uno al lado del otro. Por ejemplo, la clase [a-zA-Z]coincide con todos los caracteres alfabéticos latinos en minúsculas o mayúsculas.

Fusionando múltiples rangos

Puede fusionar varios rangos en una única clase de caracteres de rango colocándolos uno al lado del otro. Por ejemplo, la clase [a-zA-Z]coincide con todos los caracteres alfabéticos latinos en minúsculas o mayúsculas.

Combinando clases de personajes

Una unión de clases de caracteres consta de varias clases de caracteres anidadas y coincide con todos los caracteres de la unión resultante. Por ejemplo, la clase [a-d[m-p]]coincide con los caracteres de aa dy de ma p. Considere el siguiente ejemplo: java RegexDemo [ab[c-e]] abcdef este ejemplo encontrará los caracteres a, b, y , para los cuales hay coincidencias en c:deabcdef
regex = [ab[c-e]]
input = abcdef
Found [a] starting at 0 and ending at 0
Found [b] starting at 1 and ending at 1
Found [c] starting at 2 and ending at 2
Found [d] starting at 3 and ending at 3
Found [e] starting at 4 and ending at 4

Intersección de clases de personajes

La intersección de clases de caracteres consta de caracteres comunes a todas las clases anidadas y coincide sólo con los caracteres comunes. Por ejemplo, la clase coincide con [a-z&&[d-f]]los caracteres dy . Considere el siguiente ejemplo: Tenga en cuenta que en mi sistema operativo Windows, se requieren comillas dobles porque el shell de comandos las trata como un separador de comandos. Este ejemplo solo encontrará el carácter que coincida con : efjava RegexDemo "[aeiouy&&[y]]" party&yparty
regex = [aeiouy&&[y]]
input = party
Found [y] starting at 4 and ending at 4

Restando clases de personajes

La resta de clases de caracteres consta de todos los caracteres excepto los contenidos en clases de caracteres anidados y coincide solo con los caracteres restantes. Por ejemplo, la clase [a-z&&[^m-p]]coincide con los caracteres de aa ly de qa z: java RegexDemo "[a-f&&[^a-c]&&[^e]]" abcdefg este ejemplo encontrará los caracteres dy fpara los cuales hay coincidencias en abcdefg:
regex = [a-f&&[^a-c]&&[^e]]
input = abcdefg
Found [d] starting at 3 and ending at 3
Found [f] starting at 5 and ending at 5

Clases de caracteres predefinidas

Algunas clases de caracteres aparecen con suficiente frecuencia en expresiones regulares como para justificar el uso de notación taquigráfica. La clase Patternofrece clases de caracteres predefinidos como abreviaturas. Puede usarlos para simplificar sus expresiones regulares y minimizar los errores de sintaxis. Hay varias categorías de clases de caracteres predefinidas: java.lang.Characterpropiedades estándar, POSIX y Unicode, como script, bloque, categoría y binario. La siguiente lista muestra sólo la categoría de clases estándar:
  • \d: Número. Equivalente [0-9].
  • \D: Carácter no numérico. Equivalente [^0-9].
  • \s: Carácter de espacio en blanco. Equivalente [ \t\n\x0B\f\r].
  • \S: No es un carácter de espacio en blanco. Equivalente [^\s].
  • \w: Símbolo formador de palabras. Equivalente [a-zA-Z_0-9].
  • \W: No es un carácter formador de palabras. Equivalente [^\w].
El siguiente ejemplo utiliza una clase de caracteres predefinida \wpara describir todos los caracteres de palabra en el texto de entrada: java RegexDemo \w "aZ.8 _" Observe detenidamente los siguientes resultados de ejecución, que muestran que los caracteres de punto y espacio no se consideran caracteres de palabra:
regex = \w
input = aZ.8 _
Found [a] starting at 0 and ending at 0
Found [Z] starting at 1 and ending at 1
Found [8] starting at 3 and ending at 3
Found [_] starting at 5 and ending at 5
Separadores de linea
La documentación del SDK de clase Patterndescribe el metacarácter de punto como una clase de carácter predefinida que coincide con cualquier carácter excepto los separadores de línea (secuencias de uno o dos caracteres que marcan el final de una línea). La excepción es el modo dotall (que analizaremos a continuación), en el que los puntos también coinciden con los separadores de líneas. La clase Patterndistingue los siguientes separadores de línea:
  • carácter de retorno de carro ( \r);
  • carácter de nueva línea (símbolo para hacer avanzar el papel una línea) ( \n);
  • un carácter de retorno de carro seguido inmediatamente por un carácter de nueva línea ( \r\n);
  • carácter de siguiente línea ( \u0085);
  • carácter separador de línea ( \u2028);
  • símbolo separador de párrafo ( \u2029)

Grupos capturados

El grupo de captura se utiliza para guardar el conjunto de caracteres encontrado para su uso posterior en la búsqueda por patrón. Esta construcción es una secuencia de caracteres encerrados en metacaracteres entre paréntesis ( ( )). Todos los personajes dentro del grupo capturado se consideran como un todo cuando se busca por patrón. Por ejemplo, el grupo de captura ( Java) combina las letras J, ay en una sola unidad. Este grupo de captura busca todas las apariciones del patrón en el texto de entrada. Con cada coincidencia, los caracteres almacenados anteriormente son reemplazados por los siguientes. Los grupos capturados se pueden anidar dentro de otros grupos capturados. Por ejemplo, en una expresión regular, un grupo está anidado dentro de un grupo . A cada grupo de captura anidado o no anidado se le asigna un número, empezando por 1, y la numeración va de izquierda a derecha. En el ejemplo anterior, coincide con el grupo de captura número 1 y coincide con el grupo de captura número 2. En la expresión regular , coincide con el grupo de captura número 1 y con el grupo de captura número 2. Posteriormente se puede acceder a las coincidencias almacenadas por los grupos de captura mediante referencias inversas. Especificada como una barra invertida seguida de un carácter numérico correspondiente al número del grupo que se captura, la referencia inversa le permite hacer referencia a caracteres en el texto capturado por el grupo. Tener un vínculo de retroceso hace que el comparador se refiera al resultado de búsqueda almacenado del grupo capturado en función del número que contiene y luego use los caracteres de ese resultado para intentar una búsqueda adicional. El siguiente ejemplo muestra el uso de una referencia inversa para encontrar errores gramaticales en el texto: Este ejemplo usa una expresión regular para encontrar un error gramatical con una palabra duplicada inmediatamente después en el texto de entrada . Esta expresión regular especifica dos grupos para capturar: número 1 – , correspondiente a y número 2 – , correspondiente al carácter de espacio seguido de . La referencia inversa permite revisar el resultado almacenado del grupo número 2 para que el comparador pueda buscar la segunda aparición de un espacio seguida de , inmediatamente después de la primera aparición de un espacio y . Los resultados del comparador son los siguientes: vaJavaJava(Java( language))(language)(Java)(Java( language))(language)(a)(b)(a)(b)Expresiones regulares en Java, Parte 2 - 2java RegexDemo "(Java( language)\2)" "The Java language language"(Java( language)\2)languageJava"The Java language language"(Java( language)\2)Java language language(language)language\2languagelanguageRegexDemo
regex = (Java( language)\2)
input = The Java language language
Found [Java language language] starting at 4 and ending at 25

Igualadores de límites

A veces es necesario realizar una coincidencia de patrón al principio de una línea, en los límites de las palabras, al final del texto, etc. Puede hacerlo utilizando uno de los comparadores de borde de clase Pattern, que son construcciones de expresión regular que buscan coincidencias en las siguientes ubicaciones:
  • ^: Inicio de línea;
  • $: Fin de la línea;
  • \b: Límite de palabra;
  • \B: Límite de pseudopalabra;
  • \A: Inicio del texto;
  • \G: Fin del partido anterior;
  • \Z: Fin del texto, sin contar el separador de línea final (si está presente);
  • \z: Fin del texto
El siguiente ejemplo utiliza el ^metacarácter de coincidencia de límites para buscar líneas que comienzan con The, seguidas de cero o más caracteres de palabra: java RegexDemo "^The\w*" Therefore El carácter ^especifica que los primeros tres caracteres del texto de entrada deben coincidir con caracteres de patrón consecutivos y T, que pueden ir seguidos de cualquier número. de símbolos formadores de palabras. Aquí está el resultado de la ejecución: he
regex = ^The\w*
input = Therefore
Found [Therefore] starting at 0 and ending at 8
¿ Qué sucede si cambia la línea de comando a java RegexDemo "^The\w*" " Therefore"? No se encontrará ninguna coincidencia porque Thereforeel texto ingresado está precedido por un carácter de espacio.

Coincidencias de longitud cero

A veces, al trabajar con comparadores de bordes, encontrará coincidencias de longitud cero. Совпадение нулевой длиныes una coincidencia que no contiene ningún carácter. Pueden aparecer en un texto de entrada vacío, al principio del texto de entrada, después del último carácter del texto de entrada y entre dos caracteres cualesquiera del texto de entrada. Los partidos de duración cero son fáciles de reconocer porque siempre comienzan y terminan en la misma posición. Considere el siguiente ejemplo: java RegExDemo \b\b "Java is" este ejemplo busca dos límites de palabras consecutivos y los resultados se ven así:
regex = \b\b
input = Java is
Found [] starting at 0 and ending at -1
Found [] starting at 4 and ending at 3
Found [] starting at 5 and ending at 4
Found [] starting at 7 and ending at 6
Vemos varias coincidencias de duración cero en los resultados. Las posiciones finales aquí son una menos que las posiciones iniciales, ya que RegexDemolo especifiqué en el código fuente en el Listado 1 end() – 1. Expresiones regulares en Java, partes 2 - 3

Cuantificadores

Un cuantificador es una construcción de expresión regular que asocia explícita o implícitamente un patrón con un valor numérico. Este valor numérico determina cuántas veces buscar el patrón. Los cuantificadores se dividen en codiciosos, perezosos y súper codiciosos:
  • El cuantificador codicioso ( ?o ) está *diseñado +para encontrar la coincidencia más larga. Puedo preguntar X? encontrar una o menos ocurrencias X, X*encontrar cero o más ocurrencias X, X+encontrar una o más ocurrencias X, X{n}encontrar nocurrencias X, X{n,}encontrar al menos (y posiblemente más) nocurrencias Xy X{n,m}encontrar al menos npero no más mocurrencias X.
  • El cuantificador diferido ( ??o *?) +?está diseñado para encontrar la coincidencia más corta. ¿ Puede especificar X??buscar una o menos apariciones de X, X*? encontrar cero o más ocurrencias X, X+?encontrar una o más ocurrencias X, X{n}?encontrar nocurrencias X, X{n,}?encontrar al menos (y posiblemente más) nocurrencias Xy X{n,m}?encontrar al menos , npero no más, mocurrencias X.
  • El cuantificador súper codicioso ( ?+o *+) ++es similar al cuantificador codicioso, excepto que el cuantificador súper codicioso solo hace un intento para encontrar la coincidencia más larga, mientras que el cuantificador codicioso puede hacer múltiples intentos. Se puede configurar X?+para buscar una o menos ocurrencias X, X*+para encontrar cero o más ocurrencias X, X++para encontrar una o más ocurrencias X, X{n}+para buscar nocurrencias de X, X{n,}+para encontrar al menos (y posiblemente más) nocurrencias Xy X{n,m}+ para encontrar al menos , npero no más, mocurrencias X.
El siguiente ejemplo ilustra el uso del cuantificador codicioso: java RegexDemo .*ox "fox box pox" Aquí están los resultados:
regex = .*ox
input = fox box pox
Found [fox box pox] starting at 0 and ending at 10
El cuantificador codicioso ( .*) encuentra la secuencia más larga de caracteres que terminan en ox. Consume todo el texto de entrada y luego retrocede hasta que detecta que el texto de entrada termina con estos caracteres. Consideremos ahora el cuantificador perezoso: java RegexDemo .*?ox "fox box pox" sus resultados:
regex = .*?ox
input = fox box pox
Found [fox] starting at 0 and ending at 2
Found [ box] starting at 3 and ending at 6
Found [ pox] starting at 7 and ending at 10
El cuantificador diferido ( .*?) encuentra la secuencia más corta de caracteres que terminan en ox. Comienza con una cadena en blanco y gradualmente consume caracteres hasta que encuentra una coincidencia. Y luego continúa trabajando hasta que se agota el texto ingresado. Finalmente, veamos el cuantificador súper codicioso: java RegexDemo .*+ox "fox box pox" y aquí están sus resultados:
regex = .*+ox
input = fox box pox
El cuantificador extra codicioso ( .*+) no encuentra coincidencias porque consume todo el texto de entrada y no queda nada que coincidir oxal final de la expresión regular. A diferencia del cuantificador codicioso, el cuantificador súper codicioso no retrocede.

Coincidencias de longitud cero

A veces, al trabajar con cuantificadores, encontrará coincidencias de longitud cero. Por ejemplo, el uso del siguiente cuantificador codicioso da como resultado múltiples coincidencias de longitud cero: java RegexDemo a? abaa Los resultados de ejecutar este ejemplo:
regex = a?
input = abaa
Found [a] starting at 0 and ending at 0
Found [] starting at 1 and ending at 0
Found [a] starting at 2 and ending at 2
Found [a] starting at 3 and ending at 3
Found [] starting at 4 and ending at 3
Hay cinco coincidencias en los resultados de ejecución. Aunque la primera, la tercera y la cuarta son bastante esperadas (corresponden a las posiciones de tres letras aen abaa), la segunda y la quinta pueden sorprenderte. Parece que indican lo que acorresponde bal final del texto, pero en realidad no es así. La expresión regular a?no busca bal final del texto. Busca presencia o ausencia a. Cuando a?no lo encuentra a, lo informa como una coincidencia de longitud cero.

Expresiones de banderas anidadas

Los comparadores hacen algunas suposiciones predeterminadas que pueden anularse al compilar la expresión regular en un patrón. Discutiremos este tema más adelante. Una expresión regular le permite anular cualquiera de los valores predeterminados utilizando una expresión de bandera anidada. Esta construcción de expresión regular se especifica como un metacarácter entre paréntesis alrededor de un metacarácter de signo de interrogación ( ?), seguido de una letra latina minúscula. La clase Patternentiende las siguientes expresiones de banderas anidadas:
  • (?i): Habilita la coincidencia de patrones que no distingue entre mayúsculas y minúsculas. Por ejemplo, cuando se utiliza un comando, java RegexDemo (?i)tree Treehousela secuencia de caracteres Treecoincide con el patrón tree. El valor predeterminado es la búsqueda de patrones que distingue entre mayúsculas y minúsculas.
  • (?x): Permite el uso de espacios en blanco y comentarios que comiencen con el metacarácter dentro del patrón #. El comparador ignorará ambos. Por ejemplo, para java RegexDemo ".at(?x)#match hat, cat, and so on" matteruna secuencia de caracteres matcoincide con el patrón .at. De forma predeterminada, los espacios en blanco y los comentarios no están permitidos, y el comparador los trata como caracteres involucrados en la búsqueda.
  • (?s): habilita el modo dotall, en el que el metacarácter de punto coincide con los separadores de línea además de cualquier otro carácter. Por ejemplo, el comando java RegexDemo (?s). \nbuscará un carácter de nueva línea. El valor predeterminado es lo opuesto a dotall: no se encontrarán separadores de línea. Por ejemplo, el comando Java RegexDemo . \nno encontrará un carácter de nueva línea.
  • (?m): Habilita el modo multilínea, donde ^coincide con el principio y $el final de cada línea. Por ejemplo, java RegexDemo "(?m)^abc$" abc\nabcbusca ambas secuencias en el texto de entrada abc. De forma predeterminada, se utiliza el modo de una sola línea: ^coincide con el comienzo de todo el texto de entrada y $coincide con el final del mismo. Por ejemplo, java RegexDemo "^abc$" abc\nabcdevuelve una respuesta de que no hay coincidencias.
  • (?u): Habilita la alineación de mayúsculas y minúsculas que distingue Unicode. Este indicador, cuando se utiliza junto con (?i), permite la coincidencia de patrones sin distinguir entre mayúsculas y minúsculas de acuerdo con el estándar Unicode. La configuración predeterminada es buscar únicamente caracteres US-ASCII y que distingan entre mayúsculas y minúsculas.
  • (?d): Habilita el modo de cadena estilo Unix, donde el comparador reconoce metacaracteres en contexto .y solo el separador de línea . El valor predeterminado es el modo de cadena de estilo no Unix: el comparador reconoce, en el contexto de los metacaracteres anteriores, todos los delimitadores de línea.^$\n
Las expresiones de indicadores anidados se parecen a los grupos capturados porque sus caracteres están rodeados por metacaracteres entre paréntesis. A diferencia de los grupos capturados, las expresiones de banderas anidadas son un ejemplo de grupos no capturados, que son una construcción de expresión regular que no captura caracteres de texto. Se definen como secuencias de caracteres rodeados por metacaracteres entre paréntesis.
Especificación de múltiples expresiones de indicadores anidados
Es posible especificar múltiples expresiones de banderas anidadas en una expresión regular colocándolas una al lado de la otra ( (?m)(?i))) o colocando las letras que las definen secuencialmente ( (?mi)).

Conclusión

Como probablemente ya se habrá dado cuenta, las expresiones regulares son extremadamente útiles y se vuelven aún más útiles a medida que domina los matices de su sintaxis. Hasta ahora les he presentado los conceptos básicos de las expresiones regulares y Pattern. En la Parte 2, profundizaremos en la API Regex y exploraremos los métodos de Pattern, Matchery PatternSyntaxException. También te mostraré dos aplicaciones prácticas de la API Regex que puedes usar inmediatamente en tus programas. Expresiones regulares en Java, Parte 3 Expresiones regulares en Java, Parte 4 Expresiones regulares en Java, Parte 5
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION