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 clasePattern
y 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 Pattern
y . 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. Matcher
PatternSyntaxException
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
, Matcher
y PatternSyntaxException
son 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 clasePattern
es 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 contenidoregex
en una representación intermedia que se almacena en un nuevo archivoPattern
. Este método devuelve una referencia a un objeto si tiene éxito o genera una excepciónPatternSyntaxException
si se detecta una sintaxis de expresión regular no válida. Cualquier objeto de la claseMatcher
utilizadoPattern
o 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ódigoPattern p = Pattern.compile("(?m)^\\.");
crea un objetoPattern
que 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 quePattern compile(String regex)
, pero teniendo en cuentaflags
: un conjunto de constantes de bits para indicadores de bits del tipo OR. La clasePattern
declara constantesCANON_EQ, CASE_INSENSITIVE, COMMENTS, DOTALL, LITERAL, MULTILINE, UNICODE_CASE, UNICODE_CHARACTER_CLASS и UNIX_LINES
que se pueden combinar usando OR bit a bit (por ejemplo,CASE_INSENSITIVE | DOTALL
) y pasar como argumentoflags
.
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.MULTILINE
y la expresión de bandera anidada (?m)
haciendo lo mismo.
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 archivoPattern
.int flags()
devuelve las banderas del objetoPattern
.
Pattern
, normalmente se utiliza para obtener el objeto Matcher
para realizar operaciones de coincidencia de patrones. El método Matcher matcher(Charsequence input)
crea un objeto Matcher
que busca en el texto input
una 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 Matcher
el objeto Pattern
al que hace referencia la variable p
.
búsqueda única |
---|
El método static boolean matches(String regex, CharSequence input) de clase Pattern le permite ahorrar en la creación de objetos Pattern y Matcher en la búsqueda única utilizando una plantilla. Este método devuelve verdadero si input el 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 only contiene solo espacios y caracteres en minúscula. |
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 clasePattern
brinda 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 dividetext
según las coincidencias encontradas con el patrón del objetoPattern
y 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 aparecentext
.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-1
coincidencias y la longitud de la matriz no es más quelimit
elementos. - 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.
- Un valor positivo no busca más que
- 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.
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,Pattern
apareció 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 c
y 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 claseMatcher
describe 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 Matcher
admiten 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 enRegexDemo
la 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ámetrostart
. Si la búsqueda tiene éxito, se devuelve el valor booleano verdadero. Por ejemplo,m.find(1);
escanea el texto comenzando desde la posición1
(se ignora la posición 0). Si el parámetrostart
contiene un valor negativo o un valor mayor que la longitud del texto coincidente, el método genera una excepciónjava.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ódigoPattern p = Pattern.compile("\\w*"); Matcher m = p.matcher("abc!"); System.out.println(p.matches());
generafalse
porque 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étodomatches();
, 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 textoabc!
consta únicamente de caracteres que forman palabras.
Pattern
, los objetos de clase Matcher
retienen 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 actualMatcher
. Por ejemplo,m.reset();
restablece el solucionador al que hace referenciam
. -
El método
Matcher reset(CharSequence text)
restablece el estado del solucionador y establece el nuevo texto del solucionador entext
. La siguiente operación de búsqueda de patrón comienza al principio del nuevo texto coincidente. Devuelve una referencia al objeto actualMatcher
. Por ejemplo,m.reset("new text");
restablece el solucionador al que se hace referenciam
y establece el nuevo texto del solucionador en"new text"
.
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 tipojava.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 objetoStringBuffer
al que hace referencia el argumentosb
. 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 tipoString
al que hace referencia el argumentoreplacement
al final del objetoStringBuffer
(la cadenareplacement
puede 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
StringBuffer appendTail(StringBuffer sb)
agrega todo el texto a un objetoStringBuffer
y devuelve una referencia a ese objeto. Después de la última llamada al métodoappendReplacement(StringBuffer sb, String replacement)
, llame al métodoappendTail(StringBuffer sb)
para copiar el texto restante al objetoStringBuffer
.
El método Matcher appendReplacement(StringBuffer sb, String replacement)
genera una excepción java.lang.IllegalStateException
si el comparador aún no ha encontrado una coincidencia o si un intento de búsqueda anterior falló. Lanza una excepción IndexOutOfBoundsException
si la línea replacement
especifica un grupo de captura que no está en el patrón).
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. |
appendReplacement(StringBuffer sb, String replacement)
y appendTail(StringBuffer sb
para reemplazar todas las apariciones de la secuencia de caracteres en el texto fuente cat
con 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 erpillar
despué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 claseMatcher
nos 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 objetoString
, copia todos los caracteres del texto del comparador (hasta la primera coincidencia) a esta cadena, agrega los caracteres desde hasta el finalreplacement
, copia los caracteres restantes a la cadena y devuelve un objetoString
(la cadenareplacement
puede 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étodoString replaceFirst(String replacement)
, pero reemplazareplacement
todas las coincidencias encontradas con caracteres de la cadena.
\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
GO TO FULL VERSION