Las expresiones regulares se usan básicamente para procesar cadenas y es muy conveniente usarlas para hacer coincidir, extraer y reemplazar cadenas.
Sin embargo, aprender expresiones regulares sigue siendo algo difícil. Conceptos como coincidencia codiciosa, coincidencia no codiciosa, subgrupos de captura y subgrupos sin captura no solo son difíciles de entender para los principiantes, sino también para muchas personas que han trabajado durante varios años.
Entonces, ¿cuál es la mejor manera de aprender expresiones regulares? ¿Cómo dominar rápidamente las expresiones regulares?
Recomiendo una forma de aprender reglas regulares que creo que es muy buena: aprender a través de AST .
El principio de coincidencia de las expresiones regulares es analizar la cadena del patrón en AST y luego usar este AST para hacer coincidir la cadena de destino.
Diversa información en la cadena del patrón se almacenará en el AST después del análisis. AST es un árbol de sintaxis abstracta. Como su nombre indica, es un árbol organizado según una estructura gramatical. A partir de la estructura de AST, puede conocer fácilmente la sintaxis admitida por las expresiones regulares.
¿Cómo ver el AST de una expresión regular?
Puedes visualizarlo visualmente a través del sitio web astexplorer.net:
Al cambiar el lenguaje de análisis a RegExp, puede visualizar el AST de las expresiones regulares.
Como se mencionó anteriormente, AST es un árbol organizado según la gramática, por lo que se pueden separar fácilmente varias gramáticas a partir de su estructura.
Luego, aprendamos varias sintaxis desde la perspectiva de AST:
Comencemos con la simple /abc/ Tal regular puede coincidir con la cadena de 'abc', y su AST es así:
3 Char, los valores son a, b, c respectivamente, el tipo es simple. La coincidencia posterior consiste en atravesar el AST y hacer coincidir estos tres caracteres respectivamente.
Lo probamos usando la API ejecutiva:
El elemento 0 es la cadena coincidente y el índice es el índice inicial de la cadena coincidente. input es la cadena de entrada.
Probemos con caracteres especiales nuevamente:
/ddd/ significa hacer coincidir tres números d es un metacarácter (metacarácter) con un significado especial respaldado por expresiones regulares.
También podemos ver a través de AST que, aunque también son Char, su tipo es meta:
Cualquier número puede coincidir con el metacarácter d:
Cuáles son metacaracteres y cuáles son caracteres simples se pueden ver de un vistazo a través de AST.
Regular admite la especificación de un conjunto de caracteres hasta [], lo que significa que puede coincidir con cualquiera de los caracteres.
También podemos ver en AST que está envuelto con una capa de CharacterClass, que significa clase de carácter, es decir, puede coincidir con cualquier carácter que contenga.
De hecho, este es el caso bajo prueba:
Las expresiones regulares admiten especificar cuántas veces se repite un determinado carácter, usando la forma {de,a},
por ejemplo, /b{1,3}/ significa que el carácter b se repite de 1 a 3 veces. , /[abc ]{1,3}/ significa que esta clase de caracteres a/b/c se repite de 1 a 3 veces.
Como puede verse en AST, esta sintaxis se llama repetición:
Tiene un atributo de cuantificador que representa el cuantificador. El tipo aquí es rango, de 1 a 3.
Las expresiones regulares también admiten las abreviaturas de algunos cuantificadores, como + que indica de 1 a innumerables veces, * que indica de 0 a innumerables veces y?
Son diferentes tipos de cuantificadores:
Algunos estudiantes pueden preguntar, ¿qué significa aquí el atributo codicioso?
Codicioso significa codicioso. Este atributo indica si esta repetición es una coincidencia codiciosa o no codiciosa.
Si agrega un? Después del cuantificador, encontrará que codicioso se vuelve falso, lo que significa cambiar a una coincidencia no codiciosa:
Entonces, ¿qué significan codicioso y no codicioso?
Veamos un ejemplo.
La coincidencia de repetición predeterminada es codiciosa y continuará coincidiendo mientras se cumplan las condiciones, por lo que acbac se puede hacer coincidir aquí.
Agregar un ? después de que el cuantificador cambie a no codicioso, y solo el primero coincidirá:
Esta es una coincidencia codiciosa y no codiciosa. A través de AST, podemos saber claramente que codicioso y no codicioso son para gramática repetida. El valor predeterminado es agregar un cuantificador para cambiar a no codicioso.
La expresión regularadmite colocar parte de la cadena coincidente en un subgrupo y devolverla a través de ().
Eche un vistazo al AST:
El AST correspondiente se llama Grupo.
Y encontrará que tiene un atributo de captura, que por defecto es verdadero:
¿Qué quiere decir esto?
Esta es la sintaxis para la captura de subgrupos.
Si no quieres capturar subgrupos, puedes escribir así (?:aaa)
Mira, la captura se ha vuelto falsa.
¿Cuál es la diferencia entre captura y no captura?
Probémoslo:
Oh, resulta que el atributo de captura del Grupo representa si se extrae o no.
Podemos ver en el AST que la captura es para subgrupos. El valor predeterminado es captura, lo que significa que el contenido del subgrupo se extrae. Puede cambiar a no captura a través de ?: y el contenido del subgrupo no se extraerá.
Ya estamos familiarizados con el uso de AST para comprender la sintaxis regular, pero veamos algo un poco más difícil:
Las expresiones regulares admiten la expresión de aserciones anticipadas a través de la sintaxis de (?=xxx), que se utiliza para juzgar si un determinado carácter está precedido por una determinada cadena.
A través de AST, puede ver que esta sintaxis se llama Aserción y el tipo es mirar hacia adelante, lo que significa mirar hacia adelante y solo coincide con el significado anterior:
¿Qué quiere decir esto? ¿Por qué escribes esto? ¿Cuál es la diferencia entre /bbb(ccc)/ y /bbb(?:ccc)/?
Probémoslo:
Se puede ver en los resultados:
/bbb(ccc)/ coincide con el subgrupo de ccc y extrae este subgrupo porque se captura el subgrupo predeterminado.
/bbb(?:ccc)/ coincide con el subgrupo de ccc pero no se extrae porque configuramos el subgrupo para que no se capture a través de ?:.
/bbb(?=ccc)/ El subgrupo que coincide con ccc no se extrae, lo que indica que tampoco se captura. La diferencia entre este y ?: es que ccc no aparece en el resultado coincidente.
Ésta es la naturaleza de una aserción de anticipación: una aserción de anticipación significa que una determinada cadena está precedida por una determinada cadena, el subgrupo correspondiente no es de captura y la cadena afirmada no aparecerá en el resultado coincidente.
Si no va seguido de esa cadena, no coincidirá:
Cambie ?= a ?! Entonces el significado cambia. Eche un vistazo a AST:
Aunque la afirmación anticipada todavía se afirma primero, hay un atributo negativo adicional de verdadero.
El significado es obvio. Originalmente significa que el frente es una determinada cadena. Después de la negación, significa que el frente no es una determinada cadena.
Entonces el resultado coincidente es exactamente el contrario:
Ahora solo coincide si no hay una determinada cadena delante. Esta es una afirmación negativa de anticipación.
Si hay una aserción anterior, naturalmente habrá una aserción final, es decir, coincidirá solo si va seguida de una determinada cadena.
De la misma forma también se podrá negar:
Es fácil pensar en el AST correspondiente a (?<=aaa), que es una afirmación retrospectiva:
El AST correspondiente a (?<!aaa) es para agregar un atributo negativo:
La aserción de anticipación y la aserción de retrospectiva son la sintaxis de expresión regular más difícil de entender. ¿Es mucho más fácil de entender si la aprende a través de AST?
las expresiones regulares son una herramienta muy conveniente para procesar cadenas, pero aún así lo son. Es difícil de aprender. Muchas personas están confundidas acerca de la sintaxis, como la coincidencia codiciosa, la coincidencia no codiciosa, la captura de subgrupos, la no captura de subgrupos, las aserciones de anticipación, las aserciones de búsqueda hacia atrás, etc.
Recomiendo aprender reglas regulares a través de AST. AST es un árbol de objetos organizado según una estructura gramatical que se puede aclarar fácilmente a través de los nombres y atributos de los nodos AST.
Por ejemplo, hemos aclarado a través de AST:
La sintaxis de repetición (Repetición) tiene la forma de carácter + cuantificador. El valor predeterminado es coincidencia codiciosa (codicioso es verdadero), lo que significa coincidencia hasta que no se agrega un cuantificador. - Coincidencia codiciosa, se detiene cuando coincide un carácter.
La sintaxis de subgrupo (Grupo) se utiliza para extraer una determinada cadena. El valor predeterminado es capturar (la captura es verdadera), lo que significa que se requiere extracción. Puede cambiar a no capturar a través de (?: xxx), que solo coincide pero no extrae. .
La sintaxis de aserción (Aserción) representa una determinada cadena antes o después de ella. Se divide en aserción de búsqueda anticipada y aserción de búsqueda hacia atrás. La sintaxis es (? = xxx) y (? <= xxx) respectivamente. negación (negativo es verdadero), que significa exactamente lo contrario.
¿Es la comprensión profunda de la sintaxis en varios documentos o la comprensión profunda de la sintaxis en el compilador?
No es necesario preguntar, ¡debe ser el compilador!
Entonces, naturalmente, es mejor aprender gramática a través del árbol de sintaxis analizado según la gramática que mediante el documento.
Esto es cierto para las expresiones regulares y también para aprender otras gramáticas. Si puede aprender la gramática usando AST, no necesita leer la documentación.