JavaRush /Blog Java /Random-ES /Expresiones regulares en Java, Parte 3

Expresiones regulares en Java, Parte 3

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 3 - 1Expresiones regulares en Java, Parte 1 Expresiones regulares en Java, Parte 2

Simplifique las tareas de programación comunes con la API Regex

En las partes 1 y 2 de este artículo, se le presentaron las expresiones regulares y la API Regex. Aprendió sobre la clase Patterny recorrió ejemplos que demuestran construcciones de expresiones regulares, desde coincidencias de patrones simples usando cadenas literales hasta coincidencias más complejas usando rangos, comparadores de límites y cuantificadores. En esta y las siguientes partes consideraremos cuestiones no cubiertas en la primera parte, estudiaremos los métodos correspondientes de las clases Patterny . También aprenderá dos utilidades que utilizan expresiones regulares para facilitar los problemas de programación comunes. El primero extrae comentarios del código para la documentación. La segunda es una biblioteca de código reutilizable diseñada para realizar análisis léxicos, un componente esencial de ensambladores, compiladores y software similar. MatcherPatternSyntaxException

DESCARGANDO EL CÓDIGO FUENTE

Puede obtener todo el código fuente (creado por Jeff Friesen para JavaWorld) para las aplicaciones de demostración en este artículo desde aquí .

Aprendiendo la API Regex

Pattern, Matchery PatternSyntaxExceptionson las tres clases que componen la API Regex. Cada uno de ellos proporciona métodos que le permiten utilizar expresiones regulares en su código.

Métodos de la clase Patrón.

Una instancia de una clase Patternes una expresión regular compilada, también conocida como patrón. Las expresiones regulares se compilan para mejorar el rendimiento de las operaciones de coincidencia de patrones. Los siguientes métodos estáticos admiten la compilación.
  • Pattern compile(String regex)Compila el contenido regexen una representación intermedia que se almacena en un nuevo archivo Pattern. Este método devuelve una referencia a un objeto si tiene éxito o genera una excepción PatternSyntaxExceptionsi se detecta una sintaxis de expresión regular no válida. Cualquier objeto de la clase Matcherutilizado Patterno devuelto por este objeto utiliza su configuración predeterminada, como la búsqueda que distingue entre mayúsculas y minúsculas. Como ejemplo, el fragmento de código Pattern p = Pattern.compile("(?m)^\\."); crea un objeto Patternque almacena una representación compilada de una expresión regular para hacer coincidir cadenas que comienzan con un carácter de punto.

  • Pattern compile(String regex, int flags)resuelve el mismo problema que Pattern compile(String regex), pero teniendo en cuenta flags: un conjunto de constantes de bits para indicadores de bits del tipo OR. La clase Patterndeclara constantes CANON_EQ, CASE_INSENSITIVE, COMMENTS, DOTALL, LITERAL, MULTILINE, UNICODE_CASE, UNICODE_CHARACTER_CLASS и UNIX_LINESque se pueden combinar usando OR bit a bit (por ejemplo, CASE_INSENSITIVE | DOTALL) y pasar como argumento flags.

  • Con la excepción de CANON_EQ, LITERAL и UNICODE_CHARACTER_CLASS, estas constantes son una alternativa a las expresiones de bandera anidadas demostradas en la Parte 1. Si se encuentra una constante de bandera distinta de las definidas en la clase Pattern, el método Pattern compile(String regex, int flags) genera una excepción java.lang.IllegalArgumentException. Por ejemplo, Pattern p = Pattern.compile("^\\.", Pattern.MULTILINE);equivalente al ejemplo anterior, con la constante Pattern.MULTILINEy la expresión de bandera anidada (?m)haciendo lo mismo.
A veces es necesario obtener una copia de la cadena original de una expresión regular compilada en un objeto Pattern, junto con las banderas que utiliza. Para hacer esto, puede llamar a los siguientes métodos:
  • String pattern()devuelve la cadena de expresión regular original compilada en un archivo Pattern.

  • int flags()devuelve las banderas del objeto Pattern.
Después de recibir el objeto Pattern, normalmente se utiliza para obtener el objeto Matcherpara realizar operaciones de coincidencia de patrones. El método Matcher matcher(Charsequence input)crea un objeto Matcherque busca en el texto inputuna coincidencia con un patrón de objeto Pattern. Cuando se llama, devuelve una referencia a este objeto Matcher. Por ejemplo, el comando Matcher m = p.matcher(args[1]);devuelve Matcherel objeto Patternal que hace referencia la variable p.
búsqueda única
El método static boolean matches(String regex, CharSequence input)de clase Patternle permite ahorrar en la creación de objetos Patterny Matcheren la búsqueda única utilizando una plantilla. Este método devuelve verdadero si inputel patrón coincide regex; de ​​lo contrario, devuelve falso. Si la expresión regular contiene un error de sintaxis, el método genera una excepción PatternSyntaxException. Por ejemplo, System.out.println(Pattern.matches("[a-z[\\s]]*", "all lowercase letters and whitespace only"));imprime true, confirmando que la frase all lowercase letters and whitespace onlycontiene solo espacios y caracteres en minúscula.
Expresiones regulares en Java, Parte 3 - 2

Dividir texto

La mayoría de los desarrolladores han escrito al menos una vez código para dividir el texto de entrada en sus componentes, como convertir una cuenta de empleado basada en texto en un conjunto de campos. La clase Patternbrinda la capacidad de resolver más convenientemente esta tediosa tarea utilizando dos métodos de división de texto:
  • El método String[] split(CharSequence text, int limit)se divide textsegún las coincidencias encontradas con el patrón del objeto Patterny devuelve los resultados en una matriz. Cada elemento de la matriz especifica una secuencia de texto separada de la siguiente secuencia por un fragmento de texto que coincide con el patrón (o el final del texto). Los elementos de la matriz están en el mismo orden en que aparecen text.

    En este método, el número de elementos de la matriz depende del parámetro limit, que también controla el número de coincidencias que se encontrarán.

    • Un valor positivo no busca más que limit-1coincidencias y la longitud de la matriz no es más que limitelementos.
    • Si el valor es negativo, se buscan todas las coincidencias posibles y la longitud de la matriz puede ser arbitraria.
    • Si el valor es cero, se buscan todas las coincidencias posibles, la longitud de la matriz puede ser arbitraria y las líneas vacías al final se descartan.

  • El método String[] split(CharSequence text)llama al método anterior con 0 como argumento límite y devuelve el resultado de su llamada.
A continuación se muestran los resultados del método split(CharSequence text)para resolver el problema de dividir la cuenta de un empleado en campos separados de nombre, edad, dirección postal y salario:
Pattern p = Pattern.compile(",\\s");
String[] fields = p.split("John Doe, 47, Hillsboro Road, 32000");
for (int i = 0; i < fields.length; i++)
   System.out.println(fields[i]);
El código anterior describe una expresión regular para encontrar un carácter de coma seguido inmediatamente de un carácter de espacio único. Aquí están los resultados de su ejecución:
John Doe
47
Hillsboro Road
32000

Predicados de plantilla y la API Streams

En Java 8, Patternapareció un método en la clase . Este método crea un predicado (una función con un valor booleano) que se utiliza para hacer coincidir el patrón. El uso de este método se muestra en el siguiente fragmento de código: Predicate asPredicate()
List progLangs = Arrays.asList("apl", "basic", "c", "c++", "c#", "cobol", "java", "javascript", "perl", "python", "scala");
Pattern p = Pattern.compile("^c");
progLangs.stream().filter(p.asPredicate()).forEach(System.out::println);
Este código crea una lista de nombres de lenguajes de programación y luego compila un patrón para encontrar todos los nombres que comienzan con la letra c. La última línea de código anterior implementa la recepción de un flujo en serie de datos con esta lista como fuente. Configura un filtro utilizando una función booleana asPredicate()que devuelve verdadero cuando el nombre comienza con una letra cy recorre la secuencia, imprimiendo nombres coincidentes en la salida estándar. Esta última línea es equivalente al siguiente bucle normal, conocido por la aplicación RegexDemo de la Parte 1:
for (String progLang: progLangs)
   if (p.matcher(progLang).find())
      System.out.println(progLang);

Métodos de clase de comparación

Una instancia de la clase Matcherdescribe un mecanismo para realizar operaciones de coincidencia de patrones en una secuencia de caracteres interpretando la expresión regular compilada de la clase Pattern. Los objetos de la clase Matcheradmiten varios tipos de operaciones de búsqueda de patrones:
  • El método boolean find()busca en el texto de entrada la siguiente coincidencia. Este método comienza a escanear al principio del texto especificado o en el primer carácter después de la coincidencia anterior. La segunda opción solo es posible si la llamada anterior a este método devolvió verdadero y el solucionador no se restableció. En cualquier caso, si la búsqueda tiene éxito, se devuelve el valor booleano verdadero. Un ejemplo de este método se puede encontrar en RegexDemola Parte 1.

  • El método boolean find(int start)restablece el comparador y busca en el texto la siguiente coincidencia. La visualización comienza desde la posición especificada por el parámetro start. Si la búsqueda tiene éxito, se devuelve el valor booleano verdadero. Por ejemplo, m.find(1);escanea el texto comenzando desde la posición 1(se ignora la posición 0). Si el parámetro startcontiene un valor negativo o un valor mayor que la longitud del texto coincidente, el método genera una excepción java.lang.IndexOutOfBoundsException.

  • El método boolean matches()intenta hacer coincidir todo el texto con un patrón. Devuelve un valor booleano verdadero si todo el texto coincide con el patrón. Por ejemplo, el código Pattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.matches());genera falseporque el carácter !no es un carácter de palabra.

  • El método boolean lookingAt()intenta hacer coincidir el texto especificado con el patrón. Este método devuelve verdadero si alguna parte del texto coincide con el patrón. A diferencia del método matches();, no es necesario que todo el texto coincida con el patrón. Por ejemplo, Pattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.lookingAt());generará true, ya que el comienzo del texto abc!consta únicamente de caracteres que forman palabras.

A diferencia de los objetos de clase Pattern, los objetos de clase Matcherretienen información de estado. A veces es posible que necesites restablecer el comparador para borrar esta información una vez finalizada la búsqueda del patrón. Los siguientes métodos están disponibles para restablecer el solucionador:
  • El método Matcher reset()restablece el estado del comparador, incluida la posición que se agregará al final (se restablece a 0). La siguiente operación de búsqueda de patrones comienza al principio del texto coincidente. Devuelve una referencia al objeto actual Matcher. Por ejemplo, m.reset();restablece el solucionador al que hace referencia m.

  • El método Matcher reset(CharSequence text)restablece el estado del solucionador y establece el nuevo texto del solucionador en text. La siguiente operación de búsqueda de patrón comienza al principio del nuevo texto coincidente. Devuelve una referencia al objeto actual Matcher. Por ejemplo, m.reset("new text");restablece el solucionador al que se hace referencia my establece el nuevo texto del solucionador en "new text".

Expresiones regulares en Java, Parte 3 - 3

Agregar texto al final

La posición del comparador que se agregará al final especifica el comienzo del texto coincidente que se agrega al final del objeto de tipo java.lang.StringBuffer. Los siguientes métodos utilizan esta posición:
  • El método Matcher appendReplacement(StringBuffer sb, String replacement)lee los caracteres de texto coincidentes y los agrega al final del objeto StringBufferal que hace referencia el argumento sb. Este método detiene la lectura en el último carácter que precede a la coincidencia del patrón anterior. A continuación, el método agrega los caracteres del objeto de tipo Stringal que hace referencia el argumento replacemental final del objeto StringBuffer(la cadena replacementpuede contener referencias a secuencias de texto capturadas durante la búsqueda anterior; estas se especifican utilizando los caracteres ($)y números de grupo que se capturan). Finalmente, el método establece el valor de la posición del comparador que se agregará a la posición del último carácter coincidente más uno, y luego devuelve una referencia al comparador actual.

  • El método Matcher appendReplacement(StringBuffer sb, String replacement)genera una excepción java.lang.IllegalStateExceptionsi el comparador aún no ha encontrado una coincidencia o si un intento de búsqueda anterior falló. Lanza una excepción IndexOutOfBoundsExceptionsi la línea replacementespecifica un grupo de captura que no está en el patrón).

  • El método StringBuffer appendTail(StringBuffer sb)agrega todo el texto a un objeto StringBuffery devuelve una referencia a ese objeto. Después de la última llamada al método appendReplacement(StringBuffer sb, String replacement), llame al método appendTail(StringBuffer sb)para copiar el texto restante al objeto StringBuffer.

Grupos capturados
Como recordará de la Parte 1, un grupo de captura es una secuencia de caracteres encerrados entre paréntesis ( ()) metacaracteres. El propósito de esta construcción es almacenar los caracteres encontrados para su posterior reutilización durante la coincidencia de patrones. Todos los personajes del grupo capturado se consideran como un todo durante la búsqueda de patrones.
El siguiente código llama a los métodos appendReplacement(StringBuffer sb, String replacement)y appendTail(StringBuffer sbpara reemplazar todas las apariciones de la secuencia de caracteres en el texto fuente catcon caterpillar:
Pattern p = Pattern.compile("(cat)");
Matcher m = p.matcher("one cat, two cats, or three cats on a fence");
StringBuffer sb = new StringBuffer();
while (m.find())
   m.appendReplacement(sb, "$1erpillar");
m.appendTail(sb);
System.out.println(sb);
El uso de un grupo capturado y una referencia a él en el texto de reemplazo le indica al programa que inserte erpillardespués de cada aparición de cat. El resultado de ejecutar este código se ve así: one caterpillar, two caterpillars, or three caterpillars on a fence

Reemplazo de texto

La clase Matchernos proporciona dos métodos para reemplazar texto, complementarios al appendReplacement(StringBuffer sb, String replacement). Con estos métodos, puede reemplazar la primera aparición del [texto reemplazado] o todas las apariciones:
  • El método String replaceFirst(String replacement)restablece el comparador, crea un nuevo objeto String, copia todos los caracteres del texto del comparador (hasta la primera coincidencia) a esta cadena, agrega los caracteres desde hasta el final replacement, copia los caracteres restantes a la cadena y devuelve un objeto String(la cadena replacementpuede contener referencias a aquellos capturados durante las secuencias de texto de búsqueda anteriores utilizando símbolos de dólar y números de grupo capturados).

  • El método String replaceAll(String replacement)funciona de manera similar al método String replaceFirst(String replacement), pero reemplaza replacementtodas las coincidencias encontradas con caracteres de la cadena.

Una expresión regular \s+busca uno o más espacios en blanco en el texto de entrada. A continuación, usaremos esta expresión regular y llamaremos a un método replaceAll(String replacement)para eliminar espacios duplicados:
Pattern p = Pattern.compile("\\s+");
Matcher m = p.matcher("Удаляем      \t\t лишние пробелы.   ");
System.out.println(m.replaceAll(" "));
Aquí están los resultados: Удаляем лишние пробелы. 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