Saltar al contenido

Cómo encontrar una última aparición de un conjunto de caracteres en string usando expresiones regulares en java?

Agradecemos tu apoyo para extender nuestras secciones referente a las ciencias informáticas.

Solución:

Hay pocas formas de resolver el problema y la mejor dependerá del tamaño de la entrada y la complejidad del patrón:

  1. Invertir la entrada string y posiblemente el patrón, esto podría funcionar para patrones no complejos. Desafortunadamente java.util.regex no permite hacer coincidir el patrón de derecha a izquierda.

  2. En lugar de usar un cuantificador codicioso, simplemente haga coincidir el patrón y el bucle Matcher.find() hasta que se encuentre la última ocurrencia.

  3. Utilice un motor de expresiones regulares diferente con un mejor rendimiento, por ejemplo, RE2/J: coincidencia de expresiones regulares de tiempo lineal en Java.

Si la opción 2 no es lo suficientemente eficiente para su caso, le sugiero que pruebe RE2/J:

El paquete de expresiones regulares estándar de Java, java.util.regex, y muchos otros paquetes de expresiones regulares ampliamente utilizados, como PCRE, Perl y Python, utilizan una estrategia de implementación de retroceso: cuando un patrón presenta dos alternativas, como a|bel motor intentará hacer coincidir el subpatrón a primero, y si eso no produce ninguna coincidencia, restablecerá el flujo de entrada e intentará hacer coincidir b en cambio.

Si tales opciones están profundamente anidadas, esta estrategia requiere un número exponencial de pases sobre los datos de entrada antes de que pueda detectar si la entrada coincide. Si la entrada es grande, es fácil construir un patrón cuyo tiempo de ejecución exceda el tiempo de vida del universo. Esto crea un riesgo de seguridad al aceptar patrones de expresiones regulares de fuentes que no son de confianza, como los usuarios de una aplicación web.

Por el contrario, el algoritmo RE2 explora todas las coincidencias simultáneamente en un solo paso sobre los datos de entrada mediante el uso de un autómata finito no determinista.

Problemas de rendimiento con el (?s).*(x|y|z) expresiones regulares provienen del hecho de que .* el patrón es el primer subpatrón que agarra todo el string primero, y luego se retrocede para encontrar x, y o z. Si no hay partido, o el partido es al comienzo de la stringy las cadenas son muy grandes, esto puede llevar mucho tiempo.

los ([xyz])(?=[^xyz]*$) patrón parece un poco mejor: captura x, y o z y afirma que no hay otra x, y o z hasta el final de la stringpero también consume un poco de recursos debido a cada verificación anticipada después de encontrar una coincidencia.

La expresión regular más rápida para hacer su trabajo es

^(?:[^xyz]*+([xyz]))+

Concuerda

  • ^ – inicio de string
  • (?:[^xyz]*+([xyz]))+ – 1 o más repeticiones de
    • [^xyz]*+ – cualquier 0 o más caracteres que no sean x, y y z emparejado posesivamente (no se permite retroceder en el patrón)
    • ([xyz]) – Grupo 1: x, y o z.

El valor y los datos del Grupo 1 pertenecerán a la última iteración del grupo repetido (ya que todos los datos anteriores se reescriben con cada iteración posterior).

Comentarios y valoraciones

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *