stringtranslate.com

Expresión regular

Azul Los aspectos destacados muestran los resultados de la coincidencia del patrón de expresión regular: (la letra h seguida de una o más vocales)./h[aeiou]+/g

Una expresión regular (abreviada como regex o regexp ), [1] a veces denominada expresión racional , [2] [3] es una secuencia de caracteres que especifica un patrón de coincidencia en el texto . Por lo general, estos patrones son utilizados por algoritmos de búsqueda de cadenas para operaciones de "buscar" o "buscar y reemplazar" en cadenas , o para validación de entradas . Las técnicas de expresión regular se desarrollan en informática teórica y teoría del lenguaje formal .

El concepto de expresiones regulares comenzó en la década de 1950, cuando el matemático estadounidense Stephen Cole Kleene formalizó el concepto de lenguaje regular . Se volvieron de uso común con las utilidades de procesamiento de textos de Unix . Desde la década de 1980 han existido diferentes sintaxis para escribir expresiones regulares, una es el estándar POSIX y otra, ampliamente utilizada, la sintaxis Perl .

Las expresiones regulares se utilizan en motores de búsqueda , en cuadros de diálogo de búsqueda y reemplazo de procesadores de texto y editores de texto , en utilidades de procesamiento de texto como sed y AWK , y en análisis léxico . Las expresiones regulares son compatibles con muchos lenguajes de programación.

Historia

Stephen Cole Kleene , quien introdujo el concepto.

Las expresiones regulares se originaron en 1951, cuando el matemático Stephen Cole Kleene describió los lenguajes regulares utilizando su notación matemática llamada eventos regulares . [4] [5] Estos surgieron en la informática teórica , en los subcampos de la teoría de autómatas (modelos de computación) y la descripción y clasificación de lenguajes formales . Otras implementaciones tempranas de coincidencia de patrones incluyen el lenguaje SNOBOL , que no usaba expresiones regulares, sino sus propias construcciones de coincidencia de patrones.

Las expresiones regulares entraron en uso popular a partir de 1968 en dos usos: coincidencia de patrones en un editor de texto [6] y análisis léxico en un compilador. [7] Una de las primeras apariciones de expresiones regulares en forma de programa fue cuando Ken Thompson incorporó la notación de Kleene en el editor QED como un medio para hacer coincidir patrones en archivos de texto . [6] [8] [9] [10] Para mayor velocidad, Thompson implementó la coincidencia de expresiones regulares mediante compilación justo a tiempo (JIT) con el código IBM 7094 en el Compatible Time-Sharing System , un importante ejemplo temprano de compilación JIT. [11] Más tarde agregó esta capacidad al editor de Unix ed , lo que finalmente llevó al uso de expresiones regulares por parte de la popular herramienta de búsqueda grep ("grep" es una palabra derivada del comando para la búsqueda de expresiones regulares en el editor de ed: significado "Búsqueda global de líneas coincidentes de impresión y expresión regular"). [12] Casi al mismo tiempo que Thompson desarrolló QED, un grupo de investigadores, incluido Douglas T. Ross, implementó una herramienta basada en expresiones regulares que se utiliza para el análisis léxico en el diseño de compiladores . [7]g/re/p

Muchas variaciones de estas formas originales de expresiones regulares se utilizaron en programas Unix [10] en los Laboratorios Bell en la década de 1970, incluidos vi , lex , sed , AWK y expr , y en otros programas como Emacs (que tiene su propio e incompatible sintaxis y comportamiento). Posteriormente, las expresiones regulares fueron adoptadas por una amplia gama de programas, y estas primeras formas se estandarizaron en el estándar POSIX.2 en 1992.

En la década de 1980, surgieron expresiones regulares más complicadas en Perl , que originalmente derivaban de una biblioteca de expresiones regulares escrita por Henry Spencer (1986), quien más tarde escribió una implementación para Tcl llamada Expresiones regulares avanzadas . [13] La biblioteca Tcl es una implementación híbrida NFA / DFA con características de rendimiento mejoradas. Los proyectos de software que han adoptado la implementación de expresiones regulares Tcl de Spencer incluyen PostgreSQL . [14] Más tarde, Perl amplió la biblioteca original de Spencer para agregar muchas características nuevas. [15] Parte del esfuerzo en el diseño de Raku (anteriormente llamado Perl 6) es mejorar la integración de expresiones regulares de Perl y aumentar su alcance y capacidades para permitir la definición de gramáticas de expresión de análisis . [16] El resultado es un minilenguaje llamado reglas de Raku , que se utilizan para definir la gramática de Raku y para proporcionar una herramienta a los programadores en el lenguaje. Estas reglas mantienen las características existentes de las expresiones regulares de Perl 5.x, pero también permiten la definición estilo BNF de un analizador de descenso recursivo a través de subreglas.

El uso de expresiones regulares en estándares de información estructurada para el modelado de documentos y bases de datos comenzó en la década de 1960 y se expandió en la década de 1980 cuando se consolidaron estándares de la industria como ISO SGML (precursor de ANSI "GCA 101-1983"). El núcleo de los estándares del lenguaje de especificación de estructuras consta de expresiones regulares. Su uso es evidente en la sintaxis del grupo de elementos DTD . Antes del uso de expresiones regulares, muchos lenguajes de búsqueda permitían comodines simples, por ejemplo "*" para hacer coincidir cualquier secuencia de caracteres y "?" para que coincida con un solo carácter. Hoy en día se pueden encontrar reliquias de esto en la sintaxis global para nombres de archivos y en el operador SQL LIKE .

A partir de 1997, Philip Hazel desarrolló PCRE (Perl Compatible Regular Expressions), que intenta imitar fielmente la funcionalidad de expresiones regulares de Perl y es utilizado por muchas herramientas modernas, incluidas PHP y Apache HTTP Server . [ cita necesaria ]

Hoy en día, las expresiones regulares son ampliamente compatibles con lenguajes de programación, programas de procesamiento de texto (particularmente lexers ), editores de texto avanzados y algunos otros programas. La compatibilidad con Regex es parte de la biblioteca estándar de muchos lenguajes de programación, incluidos Java y Python , y está integrada en la sintaxis de otros, incluidos Perl y ECMAScript . Las implementaciones de la funcionalidad de expresiones regulares a menudo se denominan motor de expresiones regulares y hay varias bibliotecas disponibles para su reutilización. A finales de la década de 2010, varias empresas comenzaron a ofrecer implementaciones de hardware, FPGA , [17] GPU [18] de motores de expresiones regulares compatibles con PCRE que son más rápidos en comparación con las implementaciones de CPU .

Patrones

La frase expresiones regulares , o expresiones regulares , se utiliza a menudo para referirse a la sintaxis textual estándar específica para representar patrones para hacer coincidir texto, a diferencia de la notación matemática que se describe a continuación. Cada carácter de una expresión regular (es decir, cada carácter de la cadena que describe su patrón) es un metacarácter que tiene un significado especial o un carácter regular que tiene un significado literal. Por ejemplo, en la expresión regular b., 'b' es un carácter literal que coincide solo con 'b', mientras que '.' es un metacarácter que coincide con todos los caracteres excepto una nueva línea. Por lo tanto, esta expresión regular coincide, por ejemplo, con 'b%', 'bx' o 'b5'. Juntos, los metacaracteres y los caracteres literales se pueden utilizar para identificar texto de un patrón determinado o procesar varias instancias del mismo. Las coincidencias de patrones pueden variar desde una igualdad precisa hasta una similitud muy general, controlada por los metacaracteres. Por ejemplo, .es un patrón muy general [a-z](coincide con todas las letras minúsculas de 'a' a 'z') es menos general y bes un patrón preciso (coincide solo con 'b'). La sintaxis de metacaracteres está diseñada específicamente para representar objetivos prescritos de una manera concisa y flexible para dirigir la automatización del procesamiento de texto de una variedad de datos de entrada, en una forma fácil de escribir usando un teclado ASCII estándar .

Un caso muy simple de expresión regular en esta sintaxis es ubicar una palabra escrita de dos maneras diferentes en un editor de texto ; la expresión regular seriali[sz]ecoincide con "serializar" y "serializar". Los caracteres comodín también logran esto, pero están más limitados en lo que pueden modelar, ya que tienen menos metacaracteres y una base de lenguaje simple.

El contexto habitual de los caracteres comodín es incluir nombres similares en una lista de archivos, mientras que las expresiones regulares se emplean generalmente en aplicaciones que coinciden con patrones de cadenas de texto en general. Por ejemplo, la expresión regular coincide con el exceso de espacios en blanco al principio o al final de una línea. Una expresión regular avanzada que coincide con cualquier número es .^[ \t]+|[ \t]+$[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?

Traduciendo la estrella Kleene
( s * significa "cero o más de s ")

Un procesador de expresiones regulares traduce una expresión regular en la sintaxis anterior en una representación interna que puede ejecutarse y compararse con una cadena que representa el texto que se busca. Un enfoque posible es el algoritmo de construcción de Thompson para construir un autómata finito no determinista (NFA), que Luego se vuelve determinista y el autómata finito determinista (DFA) resultante se ejecuta en la cadena de texto de destino para reconocer subcadenas que coinciden con la expresión regular. La imagen muestra el esquema NFA obtenido a partir de la expresión regular , donde s denota a su vez una expresión regular más simple, que ya ha sido traducida recursivamente a NFA N ( s ).N(s*)s*

Conceptos básicos

Una expresión regular, a menudo denominada patrón , especifica un conjunto de cadenas necesarias para un propósito particular. Una forma sencilla de especificar un conjunto finito de cadenas es enumerar sus elementos o miembros. Sin embargo, a menudo hay formas más concisas: por ejemplo, el conjunto que contiene las tres cadenas "Handel", "Händel" y "Haendel" se puede especificar mediante el patrón H(ä|ae?)ndel; decimos que este patrón coincide con cada una de las tres cuerdas. Sin embargo, puede haber muchas formas de escribir una expresión regular para el mismo conjunto de cadenas: por ejemplo, (Hän|Han|Haen)delen este ejemplo también se especifica el mismo conjunto de tres cadenas.

La mayoría de los formalismos proporcionan las siguientes operaciones para construir expresiones regulares.

Booleano "o"
Una barra vertical separa las alternativas. Por ejemplo, puede coincidir con "gris" o "gris".gray|grey
Agrupamiento
Los paréntesis se utilizan para definir el alcance y la precedencia de los operadores (entre otros usos). Por ejemplo, gray|greyy son patrones equivalentes que describen el conjunto de "gris" o "gris".gr(a|e)y
Cuantificación
Un cuantificador después de un elemento (como un token , un carácter o un grupo) especifica cuántas veces se permite que se repita el elemento anterior. Los cuantificadores más comunes son el signo de interrogación ? , el asterisco * (derivado de la estrella Kleene ) y el signo más + ( Kleene plus ).
Comodín
El comodín .coincide con cualquier carácter. Por ejemplo,
a.bcoincide con cualquier cadena que contenga una "a", y luego cualquier carácter y luego "b".
a.*bcoincide con cualquier cadena que contenga una "a" y luego el carácter "b" en algún momento posterior.

Estas construcciones se pueden combinar para formar expresiones arbitrariamente complejas, de forma muy parecida a como se pueden construir expresiones aritméticas a partir de números y las operaciones +, −, × y ÷.

La sintaxis precisa de las expresiones regulares varía según las herramientas y el contexto; Se dan más detalles en § Sintaxis.

Teoría del lenguaje formal

Las expresiones regulares describen lenguajes regulares en la teoría del lenguaje formal . Tienen el mismo poder expresivo que las gramáticas regulares .

Definicion formal

Las expresiones regulares constan de constantes, que denotan conjuntos de cadenas, y símbolos de operador, que denotan operaciones sobre estos conjuntos. La siguiente definición es estándar y se encuentra como tal en la mayoría de los libros de texto sobre teoría del lenguaje formal. [20] [21] Dado un alfabeto finito Σ, las siguientes constantes se definen como expresiones regulares:

Dadas las expresiones regulares R y S, se definen las siguientes operaciones sobre ellas para producir expresiones regulares:

Para evitar paréntesis, se supone que la estrella Kleene tiene la máxima prioridad, seguida de la concatenación y luego la alternancia. Si no hay ambigüedad, se pueden omitir los paréntesis. Por ejemplo, (ab)cse puede escribir como abcy a|(b(c*))se puede escribir como a|bc*. Muchos libros de texto utilizan los símbolos ∪, + o ∨ para alternancia en lugar de la barra vertical.

Ejemplos:

Poder expresivo y compacidad.

La definición formal de expresiones regulares es mínima a propósito y evita definir ?y +; estas se pueden expresar de la siguiente manera: a+= aa*y a?= (a|ε). A veces se agrega el operador complemento para dar una expresión regular generalizada ; aquí R c coincide con todas las cadenas sobre Σ* que no coinciden con R . En principio, el operador complemento es redundante, porque no otorga ningún poder más expresivo. Sin embargo, puede hacer que una expresión regular sea mucho más concisa: eliminar un operador de complemento único puede provocar una doble ampliación exponencial de su longitud. [22] [23] [24]

Las expresiones regulares en este sentido pueden expresar los lenguajes regulares, exactamente la clase de lenguajes aceptados por los autómatas finitos deterministas . Sin embargo, existe una diferencia significativa en la compacidad. Algunas clases de lenguajes regulares sólo pueden describirse mediante autómatas finitos deterministas cuyo tamaño crece exponencialmente en el tamaño de las expresiones regulares equivalentes más cortas. El ejemplo estándar aquí son los idiomas L k que consisten en todas las cadenas sobre el alfabeto { a , b } cuya k ésima desde la última letra es igual  a . Por un lado, una expresión regular que describe L 4 viene dada por .

Generalizando este patrón a L k se obtiene la expresión:

Por otro lado, se sabe que todo autómata finito determinista que acepte el lenguaje L k debe tener al menos 2 k estados. Afortunadamente, existe un mapeo simple de expresiones regulares a los autómatas finitos no deterministas (NFA) más generales que no conduce a tal aumento de tamaño; por esta razón, los NFA se utilizan a menudo como representaciones alternativas de lenguajes regulares. Las NFA son una variación simple de las gramáticas de tipo 3 de la jerarquía de Chomsky . [20]

En la dirección opuesta, hay muchos lenguajes que un DFA describe fácilmente y que no se describen fácilmente mediante una expresión regular. Por ejemplo, determinar la validez de un ISBN determinado requiere calcular el módulo del número entero en base 11, y se puede implementar fácilmente con un DFA de 11 estados. Sin embargo, una expresión regular para responder al mismo problema de divisibilidad entre 11 tiene al menos varios megabytes de longitud. [ cita necesaria ]

Dada una expresión regular, el algoritmo de construcción de Thompson calcula un autómata finito no determinista equivalente. El algoritmo de Kleene logra una conversión en la dirección opuesta .

Finalmente, vale la pena señalar que muchos motores de "expresiones regulares" del mundo real implementan características que las expresiones regulares no pueden describir en el sentido de la teoría del lenguaje formal; más bien, implementan expresiones regulares . Consulte a continuación para obtener más información sobre esto.

Decidir la equivalencia de expresiones regulares

Como se ve en muchos de los ejemplos anteriores, hay más de una forma de construir una expresión regular para lograr los mismos resultados.

Es posible escribir un algoritmo que, para dos expresiones regulares dadas, decida si los lenguajes descritos son iguales; el algoritmo reduce cada expresión a una máquina de estados finitos determinista mínima y determina si son isomorfas (equivalentes).

Las leyes algebraicas para expresiones regulares se pueden obtener utilizando un método de Gischer que se explica mejor con un ejemplo: Para comprobar si ( X + Y ) * y ( X * Y * ) * denotan el mismo lenguaje regular, para todas las expresiones regulares X , Y , es necesario y suficiente comprobar si las expresiones regulares particulares ( a + b ) * y ( a * b * ) * denotan el mismo idioma sobre el alfabeto Σ={ a , b }. De manera más general, una ecuación E = F entre términos de expresiones regulares con variables se cumple si, y sólo si, se cumple su instanciación con diferentes variables reemplazadas por diferentes símbolos constantes. [25] [26]

Cada expresión regular puede escribirse únicamente en términos de la estrella de Kleene y establecer uniones sobre palabras finitas. Éste es un problema sorprendentemente difícil. Por más simples que sean las expresiones regulares, no existe ningún método para reescribirlas sistemáticamente en alguna forma normal. La falta de un axioma en el pasado llevó al problema de la altura de las estrellas . En 1991, Dexter Kozen axiomatizó las expresiones regulares como un álgebra de Kleene , utilizando axiomas ecuacionales y de la cláusula de Horn . [27] Ya en 1964, Redko había demostrado que ningún conjunto finito de axiomas puramente ecuacionales puede caracterizar el álgebra de los lenguajes regulares. [28]

Sintaxis

Un patrón de expresiones regulares coincide con una cadena de destino . El patrón está compuesto por una secuencia de átomos . Un átomo es un punto único dentro del patrón de expresiones regulares que intenta hacer coincidir con la cadena objetivo. El átomo más simple es un literal, pero agrupar partes del patrón para que coincidan con un átomo requerirá su uso ( )como metacaracteres. Los metacaracteres ayudan a formar: átomos ; cuantificadores que dicen cuántos átomos (y si es un cuantificador codicioso o no); un carácter lógico OR, que ofrece un conjunto de alternativas, y un carácter lógico NOT, que niega la existencia de un átomo; y referencias retrospectivas para referirse a átomos anteriores de un patrón de átomos completo. Se realiza una coincidencia, no cuando todos los átomos de la cadena coinciden, sino cuando todos los átomos del patrón en la expresión regular coinciden. La idea es hacer que un pequeño patrón de caracteres represente una gran cantidad de cadenas posibles, en lugar de compilar una lista grande de todas las posibilidades literales.

Dependiendo del procesador de expresiones regulares, hay alrededor de catorce metacaracteres, caracteres que pueden tener o no su significado literal , según el contexto, o si están "escapados", es decir, precedidos por una secuencia de escape , en este caso, la barra invertida \. Las expresiones regulares modernas y extendidas POSIX usan metacaracteres con más frecuencia que su significado literal, por lo que para evitar la "barra invertida" o el síndrome del palillo inclinado , tienen un escape de metacaracteres a un modo literal; Sin embargo, al principio tienen los cuatro metacaracteres entre corchetes ( )y { }son principalmente literales, y "escapan" de este significado habitual para convertirse en metacaracteres. Los estándares comunes implementan ambos. Los metacaracteres habituales son {}[]()^$.|*+?y \. Los personajes habituales que se convierten en metacaracteres cuando se escapan son dswDSWy N.

Delimitadores

Al ingresar una expresión regular en un lenguaje de programación, se puede representar como una cadena literal habitual, por lo que generalmente se cita entre comillas; esto es común en C, Java y Python, por ejemplo, donde la expresión regular rese ingresa como "re". Sin embargo, a menudo se escriben con barras diagonales como delimitadores , como en el /re/caso de la expresión regular re. Esto se origina en ed , donde /está el comando del editor para realizar búsquedas, y /re/se puede usar una expresión para especificar un rango de líneas (que coincidan con el patrón), que se puede combinar con otros comandos en cualquier lado, el más famoso g/re/pcomo en grep ("global regex print"), que se incluye en la mayoría de los sistemas operativos basados ​​en Unix , como las distribuciones de Linux . Se utiliza una convención similar en sed , donde la búsqueda y el reemplazo vienen dados por s/re/replacement/y los patrones se pueden unir con una coma para especificar un rango de líneas como en /re1/,/re2/. Esta notación es particularmente conocida debido a su uso en Perl , donde forma parte de la sintaxis distinta de los literales de cadena normales. En algunos casos, como sed y Perl, se pueden utilizar delimitadores alternativos para evitar colisiones con los contenidos y para evitar tener que escapar de las apariciones del carácter delimitador en los contenidos. Por ejemplo, en sed el comando s,/,X,reemplazará a /por an X, usando comas como delimitadores.

Estándares

El estándar IEEE POSIX tiene tres conjuntos de cumplimiento: BRE (Expresiones regulares básicas), [29] ERE (Expresiones regulares extendidas) y SRE (Expresiones regulares simples). SRE está en desuso , [30] a favor de BRE, ya que ambos proporcionan compatibilidad con versiones anteriores . La siguiente subsección que cubre las clases de caracteres se aplica tanto a BRE como a ERE.

BRE y ERE trabajan juntos. ERE agrega ?, +y |, y elimina la necesidad de escapar de los metacaracteres ( )y { }, que son necesarios en BRE. Además, siempre que se respete la sintaxis estándar POSIX para expresiones regulares, puede haber, y a menudo hay, sintaxis adicional para servir aplicaciones específicas (aunque compatibles con POSIX). Aunque POSIX.2 deja algunos detalles de implementación sin definir, BRE y ERE proporcionan un "estándar" que desde entonces se ha adoptado como la sintaxis predeterminada de muchas herramientas, donde la elección de los modos BRE o ERE suele ser una opción compatible. Por ejemplo, GNU grep tiene las siguientes opciones: " grep -E" para ERE, " grep -G" para BRE (el valor predeterminado) y " grep -P" para expresiones regulares de Perl .

Las expresiones regulares de Perl se han convertido en un estándar de facto, ya que tienen un conjunto rico y poderoso de expresiones atómicas. Perl no tiene niveles "básicos" ni "extendidos". Como en los ERE POSIX, ( )y { }se tratan como metacaracteres a menos que se les escape; Se sabe que otros metacaracteres son literales o simbólicos basándose únicamente en el contexto. La funcionalidad adicional incluye coincidencia diferida, referencias inversas, grupos de captura con nombre y patrones recursivos .

POSIX básico y extendido

En el estándar POSIX , la sintaxis regular básica ( BRE ) requiere que los metacaracteres ( ) y { }estén designados \(\)y \{\}, mientras que la sintaxis regular extendida ( ERE ) no.

Ejemplos:

Según Ross Cox, la especificación POSIX requiere que las subexpresiones ambiguas se manejen de una manera diferente a la de Perl. El comité reemplazó las reglas de Perl por una que es fácil de explicar, pero las nuevas reglas "simples" son en realidad más complejas de implementar: eran incompatibles con las herramientas preexistentes y hacían esencialmente imposible definir una "coincidencia diferida" (ver más abajo). ) extensión. Como resultado, muy pocos programas implementan realmente las reglas de subexpresión POSIX (incluso cuando implementan otras partes de la sintaxis POSIX). [32]

POSIX extendido

El significado de los metacaracteres con una barra invertida se invierte para algunos caracteres en la sintaxis de expresión regular extendida ( ERE ) de POSIX. Con esta sintaxis, una barra invertida hace que el metacarácter se trate como un carácter literal. Así, por ejemplo, \( \)es ahora ( )y \{ \}es ahora { }. Además, se elimina la compatibilidad con referencias anteriores y se agregan los siguientes metacaracteres:\n

Ejemplos:

Las expresiones regulares extendidas POSIX a menudo se pueden usar con utilidades modernas de Unix al incluir el indicador de línea de comando -E .

Clases de personajes

La clase de personaje es el concepto de expresión regular más básico después de una coincidencia literal. Hace que una pequeña secuencia de caracteres coincida con un conjunto más grande de caracteres. Por ejemplo, [A-Z]podría representar cualquier letra mayúscula del alfabeto inglés y podría significar cualquier dígito. Las clases de caracteres se aplican a ambos niveles POSIX.\d

Al especificar un rango de caracteres, como [a-Z](es decir, de minúsculas aa mayúsculas Z), la configuración regional de la computadora determina el contenido mediante el orden numérico de la codificación de caracteres. Podrían almacenar dígitos en esa secuencia, o el orden podría ser abc...zABC...Z o aAbBcC...zZ . Entonces, el estándar POSIX define una clase de carácter, que será conocida por el procesador de expresiones regulares instalado. Esas definiciones se encuentran en la siguiente tabla:

Las clases de caracteres POSIX solo se pueden utilizar dentro de expresiones entre corchetes. Por ejemplo, coincide con las letras mayúsculas y minúsculas "a" y "b".[[:upper:]ab]

Una clase adicional que no es POSIX y que algunas herramientas entienden es [:word:], que generalmente se define como [:alnum:]guión bajo más. Esto refleja el hecho de que en muchos lenguajes de programación estos son los caracteres que pueden usarse en los identificadores. El editor Vim distingue además las clases de palabras y cabezas de palabras (usando la notación y ), ya que en muchos lenguajes de programación los caracteres que pueden comenzar un identificador no son los mismos que los que pueden aparecer en otras posiciones: los números generalmente se excluyen, por lo que un identificador se vería como o en notación POSIX.\w\h\h\w*[[:alpha:]_][[:alnum:]_]*

Tenga en cuenta que lo que los estándares de expresiones regulares POSIX llaman clases de caracteres se denominan comúnmente clases de caracteres POSIX en otros tipos de expresiones regulares que las admiten. Con la mayoría de los otros tipos de expresiones regulares, el término clase de carácter se usa para describir lo que POSIX llama expresiones entre corchetes .

Perl y PCRE

Debido a su poder expresivo y (relativa) facilidad de lectura, muchas otras utilidades y lenguajes de programación han adoptado una sintaxis similar a la de Perl , por ejemplo, Java , JavaScript , Julia , Python , Ruby , Qt , .NET Framework de Microsoft y XML . Esquema . Algunos lenguajes y herramientas como Boost y PHP admiten múltiples tipos de expresiones regulares. Las implementaciones de expresiones regulares derivadas de Perl no son idénticas y generalmente implementan un subconjunto de características que se encuentran en Perl 5.0, lanzado en 1994. Perl a veces incorpora características que se encuentran inicialmente en otros lenguajes. Por ejemplo, Perl 5.10 implementa extensiones sintácticas desarrolladas originalmente en PCRE y Python. [33]

Emparejamiento perezoso

En Python y algunas otras implementaciones (por ejemplo, Java), los tres cuantificadores comunes ( *, +y ?) son codiciosos de forma predeterminada porque coinciden con tantos caracteres como sea posible. [34] La expresión regular ".+"(incluidas las comillas dobles) aplicada a la cadena

"Ganimedes", continuó, "es la luna más grande del Sistema Solar".

coincide con toda la línea (porque toda la línea comienza y termina con comillas dobles) en lugar de coincidir solo con la primera parte, "Ganymede,". Sin embargo, los cuantificadores antes mencionados pueden volverse vagos , mínimos o reacios , haciendo coincidir la menor cantidad de caracteres posible, agregando un signo de interrogación: ".+?"solo coincidencias "Ganymede,". [34]

emparejamiento posesivo

En Java y Python 3.11+, [35] los cuantificadores pueden volverse posesivos agregando un signo más, que inhabilita el retroceso (en un motor de retroceso), incluso si hacerlo permitiría que la coincidencia general fuera exitosa: [36] Mientras que la expresión regular ".*"aplicado a la cuerda

"Ganimedes", continuó, "es la luna más grande del Sistema Solar".

coincide con toda la línea, la expresión regular ".*+"no coincide en absoluto , porque .*+consume toda la entrada, incluido el final ". Por tanto, los cuantificadores posesivos son más útiles con clases de caracteres negados, por ejemplo "[^"]*+", que coinciden "Ganymede,"cuando se aplican a la misma cadena.

Otra extensión común que cumple la misma función es la agrupación atómica, que deshabilita el retroceso para un grupo entre paréntesis. La sintaxis típica es (?>group) . Por ejemplo, mientras ^(wi|w)i$ coincide con wi y wii , ^(?>wi|w)i$ solo coincide con wii porque el motor tiene prohibido retroceder y, por lo tanto, no puede intentar configurar el grupo en "w" después "wi" coincidente. [37]

Los cuantificadores posesivos son más fáciles de implementar que los cuantificadores codiciosos y perezosos y, por lo general, son más eficientes en tiempo de ejecución. [36]

Patrones para lenguajes no regulares

Muchas características que se encuentran en prácticamente todas las bibliotecas de expresiones regulares modernas brindan un poder expresivo que excede los lenguajes regulares . Por ejemplo, muchas implementaciones permiten agrupar subexpresiones con paréntesis y recuperar el valor que coinciden en la misma expresión (referencias anteriores ). Esto significa que, entre otras cosas, un patrón puede coincidir con cadenas de palabras repetidas como "papá" o "WikiWiki", llamadascuadradosen la teoría del lenguaje formal. El patrón de estas cuerdas es(.+)\1.

El lenguaje de los cuadrados no es regular ni está libre de contexto , debido al lema de bombeo . Sin embargo, la coincidencia de patrones con un número ilimitado de referencias anteriores, respaldada por numerosas herramientas modernas, sigue siendo sensible al contexto . [38] El problema general de hacer coincidir cualquier número de referencias inversas es NP-completo , y el tiempo de ejecución de algoritmos conocidos crece exponencialmente según la cantidad de grupos de referencias inversas utilizados. [39]

Sin embargo, muchas herramientas, bibliotecas y motores que proporcionan este tipo de construcciones todavía utilizan el término expresión regular para sus patrones. Esto ha llevado a una nomenclatura en la que el término expresión regular tiene diferentes significados en la teoría del lenguaje formal y la coincidencia de patrones. Por esta razón, algunas personas han empezado a utilizar el término expresión regular , expresión regular o simplemente patrón para describir este último. Larry Wall , autor del lenguaje de programación Perl, escribe en un ensayo sobre el diseño de Raku:

Las "expresiones regulares" […] están sólo marginalmente relacionadas con las expresiones regulares reales. Sin embargo, el término ha crecido con las capacidades de nuestros motores de coincidencia de patrones, por lo que no voy a intentar luchar aquí contra la necesidad lingüística. Sin embargo, generalmente los llamaré "regexen" (o "regexen", cuando estoy en un estado de ánimo anglosajón). [dieciséis]

Afirmaciones

Otras características que no se encuentran en la descripción de lenguajes regulares incluyen las afirmaciones. Estos incluyen el omnipresente ^y $, utilizado al menos desde 1970, [40] así como algunas extensiones más sofisticadas como lookaround que apareció en 1994. [41] Los lookarounds definen el entorno de una partida y no se extienden a la partida en sí, una característica Sólo es relevante para el caso de uso de búsqueda de cadenas [ cita requerida ] . Algunos de ellos pueden simularse en un lenguaje normal tratando el entorno también como parte del lenguaje. [42]

Elaserciones de anticipación (?=...) y(?!...)han sido atestiguadas desde al menos 1994, comenzando con Perl 5. [41] Las afirmaciones de anticipación(?<=...)y(?<!...)están atestiguadas desde 1997 en un compromiso de Ilya Zakharevich con Perl 5.005. [43]

Implementaciones y tiempos de ejecución.

Hay al menos tres algoritmos diferentes que deciden si una expresión regular determinada coincide con una cadena y cómo.

El más antiguo y rápido se basa en un resultado de la teoría del lenguaje formal que permite que cada autómata finito no determinista (NFA) se transforme en un autómata finito determinista (DFA). El DFA se puede construir explícitamente y luego ejecutarse en la cadena de entrada resultante, un símbolo a la vez. La construcción del DFA para una expresión regular de tamaño m tiene un costo de tiempo y memoria de O (2 m ), pero se puede ejecutar en una cadena de tamaño n en un tiempo O ( n ). Tenga en cuenta que el tamaño de la expresión es el tamaño después de que se hayan ampliado las abreviaturas, como los cuantificadores numéricos.

Un enfoque alternativo es simular la NFA directamente, esencialmente construyendo cada estado de DFA según la demanda y luego descartándolo en el siguiente paso. Esto mantiene el DFA implícito y evita el costo de construcción exponencial, pero el costo de funcionamiento aumenta a O ( mn ). El enfoque explícito se denomina algoritmo DFA y el enfoque implícito, algoritmo NFA. Agregar almacenamiento en caché al algoritmo NFA a menudo se denomina algoritmo "DFA diferido", o simplemente algoritmo DFA sin hacer distinción. Estos algoritmos son rápidos, pero usarlos para recordar subexpresiones agrupadas, cuantificación diferida y características similares es complicado. [44] [45] Las implementaciones modernas incluyen la familia re1- re2 -sregex basada en el código de Cox.

El tercer algoritmo consiste en hacer coincidir el patrón con la cadena de entrada retrocediendo . Este algoritmo se denomina comúnmente NFA, pero esta terminología puede resultar confusa. Su tiempo de ejecución puede ser exponencial, lo que exhiben implementaciones simples cuando se comparan con expresiones como las que contienen alternancia y cuantificación ilimitada y obligan al algoritmo a considerar un número exponencialmente creciente de subcasos. Este comportamiento puede causar un problema de seguridad llamado Denegación de servicio de expresión regular (ReDoS).(a|aa)*b

Aunque las implementaciones de retroceso solo ofrecen una garantía exponencial en el peor de los casos, proporcionan mucha mayor flexibilidad y poder expresivo. Por ejemplo, cualquier implementación que permita el uso de referencias retrospectivas, o que implemente las diversas extensiones introducidas por Perl, debe incluir algún tipo de retroceso. Algunas implementaciones intentan ofrecer lo mejor de ambos algoritmos ejecutando primero un algoritmo DFA rápido y volviendo a un algoritmo de retroceso potencialmente más lento solo cuando se encuentra una referencia inversa durante la coincidencia. GNU grep (y el gnulib DFA subyacente) utiliza dicha estrategia. [46]

Se han logrado algoritmos de tiempo de ejecución sublineal utilizando algoritmos basados ​​en Boyer-Moore (BM) y técnicas de optimización DFA relacionadas, como el escaneo inverso. [47] GNU grep, que admite una amplia variedad de sintaxis y extensiones POSIX, utiliza BM para un prefiltrado de primer paso y luego utiliza un DFA implícito. Wu agrep , que implementa una coincidencia aproximada, combina el filtrado previo en DFA en BDM (coincidencia DAWG hacia atrás). BNDM de NR-grep amplía la técnica BDM con paralelismo a nivel de bits Shift-Or. [48]

Existen algunas alternativas teóricas al retroceso de las referencias retrospectivas, y sus "exponentes" son más suaves porque solo están relacionados con el número de referencias retrospectivas, una propiedad fija de algunos lenguajes de expresiones regulares como POSIX. Un método ingenuo que duplica un NFA sin seguimiento para cada nota de referencia tiene una complejidad de tiempo y espacio para un pajar de longitud n y k referencias en RegExp. [49] Un trabajo teórico muy reciente basado en autómatas de memoria proporciona un límite más estricto basado en los nodos variables "activos" utilizados y una posibilidad polinómica para algunas expresiones regulares con referencias inversas. [50]

Unicódigo

En términos teóricos, cualquier conjunto de tokens puede coincidir con expresiones regulares siempre que esté predefinido. En términos de implementaciones históricas, las expresiones regulares se escribieron originalmente para usar caracteres ASCII como conjunto de tokens, aunque las bibliotecas de expresiones regulares han admitido muchos otros conjuntos de caracteres . Muchos motores de expresiones regulares modernos ofrecen al menos algo de soporte para Unicode . En la mayoría de los aspectos, no importa cuál sea el conjunto de caracteres, pero surgen algunos problemas al extender las expresiones regulares para admitir Unicode.

Ayuda de idioma

La mayoría de los lenguajes de programación de propósito general admiten capacidades de expresiones regulares, ya sea de forma nativa o mediante bibliotecas . El soporte integral está incluido en:

Usos

Una lista negra en Wikipedia que utiliza expresiones regulares para identificar títulos incorrectos

Las expresiones regulares son útiles en una amplia variedad de tareas de procesamiento de texto y, en general , en el procesamiento de cadenas , donde los datos no necesitan ser textuales. Las aplicaciones comunes incluyen validación de datos , raspado de datos (especialmente raspado web ), manipulación de datos , análisis simple , producción de sistemas de resaltado de sintaxis y muchas otras tareas.

Si bien las expresiones regulares serían útiles en los motores de búsqueda de Internet , procesarlas en toda la base de datos podría consumir recursos informáticos excesivos dependiendo de la complejidad y el diseño de la expresión regular. Aunque en muchos casos los administradores de sistemas pueden ejecutar consultas basadas en expresiones regulares internamente, la mayoría de los motores de búsqueda no ofrecen soporte para expresiones regulares al público. Las excepciones notables incluyen Google Code Search y Exalead . Sin embargo, Google Code Search se cerró en enero de 2012. [62]

Ejemplos

Las reglas de sintaxis específicas varían según la implementación específica, el lenguaje de programación o la biblioteca en uso. Además, la funcionalidad de las implementaciones de expresiones regulares puede variar entre versiones .

Debido a que las expresiones regulares pueden ser difíciles de explicar y comprender sin ejemplos, los sitios web interactivos para probar expresiones regulares son un recurso útil para aprenderlas mediante experimentación. Esta sección proporciona una descripción básica de algunas de las propiedades de las expresiones regulares a modo de ilustración.

En los ejemplos se utilizan las siguientes convenciones. [63]

metacaracteres ;; la columna de metacaracteres especifica la sintaxis de expresiones regulares que se demuestra=~ m// ;; indica una operación de coincidencia de expresiones regulares en Perl=~ s/// ;; indica una operación de sustitución de expresiones regulares en Perl

También vale la pena señalar que estas expresiones regulares tienen una sintaxis similar a Perl. Las expresiones regulares POSIX estándar son diferentes.

A menos que se indique lo contrario, los siguientes ejemplos se ajustan al lenguaje de programación Perl , versión 5.8.8, 31 de enero de 2006. Esto significa que otras implementaciones pueden carecer de soporte para algunas partes de la sintaxis que se muestra aquí (por ejemplo, expresiones regulares básicas versus extendidas, \( \)versus expresiones regulares. (), o falta de \den lugar de POSIX [:digit:] ).

La sintaxis y las convenciones utilizadas en estos ejemplos también coinciden con las de otros entornos de programación. [64]

Inducción

Las expresiones regulares a menudo se pueden crear ("inducir" o "aprender") basándose en un conjunto de cadenas de ejemplo. Esto se conoce como inducción de lenguajes regulares y es parte del problema general de la inducción gramatical en la teoría del aprendizaje computacional . Formalmente, dados ejemplos de cadenas en un lenguaje regular, y quizás también ejemplos de cadenas que no están en ese lenguaje regular, es posible inducir una gramática para el lenguaje, es decir, una expresión regular que genera ese lenguaje. No todos los lenguajes regulares pueden inducirse de esta manera (ver identificación de lenguaje en el límite ), pero muchos sí. Por ejemplo, el conjunto de ejemplos {1, 10, 100} y el conjunto negativo (de contraejemplos) {11, 1001, 101, 0} se pueden utilizar para inducir la expresión regular 1⋅0* (1 seguido de cero o más 0).

Ver también

Notas

  1. ^ Goyvaerts, enero. "Tutorial de expresiones regulares: aprenda a utilizar expresiones regulares". Expresiones-regulares.info . Archivado desde el original el 1 de noviembre de 2016 . Consultado el 31 de octubre de 2016 .
  2. ^ Mitkov, Ruslán (2003). El manual de Oxford de lingüística computacional. Prensa de la Universidad de Oxford. pag. 754.ISBN _ 978-0-19-927634-9. Archivado desde el original el 28 de febrero de 2017 . Consultado el 25 de julio de 2016 .
  3. ^ Lawson, Mark V. (17 de septiembre de 2003). Autómatas finitos. Prensa CRC. págs. 98-100. ISBN 978-1-58488-255-8. Archivado desde el original el 27 de febrero de 2017 . Consultado el 25 de julio de 2016 .
  4. ^ Kleine 1951.
  5. ^ Leung, Hing (16 de septiembre de 2010). "Lenguajes regulares y autómatas finitos" (PDF) . Universidad Estatal de Nuevo México . Archivado desde el original (PDF) el 5 de diciembre de 2013 . Consultado el 13 de agosto de 2019 . Kleene introdujo el concepto de eventos regulares mediante la definición de expresiones regulares.
  6. ^ ab Thompson 1968.
  7. ^ ab Johnson y col. 1968.
  8. ^ Kernighan, Brian (8 de agosto de 2007). "Un comparador de expresiones regulares". Hermoso código . Medios O'Reilly . págs. 1–2. ISBN 978-0-596-51004-6. Archivado desde el original el 7 de octubre de 2020 . Consultado el 15 de mayo de 2013 .
  9. ^ Ritchie, Dennis M. "Una historia incompleta del editor de texto QED". Archivado desde el original el 21 de febrero de 1999 . Consultado el 9 de octubre de 2013 .
  10. ^ ab Aho & Ullman 1992, 10.11 Notas bibliográficas para el capítulo 10, p. 589.
  11. ^ Aycock 2003, pag. 98.
  12. ^ Raymond, Eric S. citando a Dennis Ritchie (2003). "Archivo de jerga 4.4.7: grep". Archivado desde el original el 5 de junio de 2011 . Consultado el 17 de febrero de 2009 .
  13. ^ "Nuevas funciones de expresiones regulares en Tcl 8.1". Archivado desde el original el 7 de octubre de 2020 . Consultado el 11 de octubre de 2013 .
  14. ^ "Documentación: 9.3: Coincidencia de patrones". PostgreSQL . Archivado desde el original el 7 de octubre de 2020 . Consultado el 12 de octubre de 2013 .
  15. ^ Muro, Larry (2006). "Expresiones regulares de Perl". perlre . Archivado desde el original el 31 de diciembre de 2009 . Consultado el 10 de octubre de 2006 .
  16. ^ ab Pared (2002)
  17. ^ "GRegex: análisis más rápido para datos de texto no estructurados". grovf.com . Archivado desde el original el 7 de octubre de 2020 . Consultado el 22 de octubre de 2019 .
  18. ^ "Grupo CUDA". bkase.github.io . Archivado desde el original el 7 de octubre de 2020 . Consultado el 22 de octubre de 2019 .
  19. ^ abcd Kerrisk, Michael. "grep(1) - página del manual de Linux". man7.org . Consultado el 31 de enero de 2023 .
  20. ^ ab Hopcroft, Motwani y Ullman (2000)
  21. ^ Sorbedor (1998)
  22. ^ Gelade y Neven (2008, p.332, Thm.4.1)
  23. ^ Gruber y Holzer (2008)
  24. ^ Basado en Gelade & Neven (2008), se puede encontrar una expresión regular de longitud aproximada de 850 tal que su complemento tenga una longitud de aproximadamente 2 32 en Archivo: RegexComplementBlowup.png .
  25. ^ Gischer, Jay L. (1984). (Título desconocido) (Informe técnico). Universidad de Stanford, Departamento de Comp. Carolina del Sur.[ falta título ]
  26. ^ Hopcroft, John E.; Motwani, Rajeev y Ullman, Jeffrey D. (2003). Introducción a la teoría, los lenguajes y la computación de autómatas . Upper Saddle River, Nueva Jersey: Addison Wesley. págs. 117-120. ISBN 978-0-201-44124-6. Esta propiedad no tiene por qué ser válida para expresiones regulares extendidas, incluso si no describen una clase más grande que los lenguajes regulares; cf. pág.121.
  27. ^ Kozen (1991) [ página necesaria ]
  28. ^ Redko, VN (1964). "Sobre la definición de relaciones para el álgebra de eventos regulares". Ukrainskii Matematicheskii Zhurnal (en ruso). 16 (1): 120–126. Archivado desde el original el 29 de marzo de 2018 . Consultado el 28 de marzo de 2018 .
  29. ^ ISO/IEC 9945-2:1993 Tecnología de la información - Interfaz del sistema operativo portátil (POSIX) - Parte 2: Shell y utilidades , revisada sucesivamente como ISO/IEC 9945-2:2002 Tecnología de la información - Interfaz del sistema operativo portátil (POSIX) - Parte 2: Interfaces del sistema , ISO/IEC 9945-2:2003 y actualmente ISO/IEC/IEEE 9945:2009 Tecnología de la información: especificaciones básicas de la interfaz del sistema operativo portátil (POSIX), edición 7
  30. ^ La especificación única de Unix (versión 2)
  31. ^ "9.3.6 BRE que coinciden con varios caracteres". Especificaciones básicas de Open Group Número 7, edición de 2018 . El grupo abierto. 2017 . Consultado el 10 de diciembre de 2023 .
  32. ^ Ross Cox (2009). "Coincidencia de expresiones regulares: el enfoque de la máquina virtual". swtch.com . Digresión: subcoincidencia POSIX
  33. ^ "Documentación de expresiones regulares de Perl". perldoc.perl.org. Archivado desde el original el 31 de diciembre de 2009 . Consultado el 8 de enero de 2012 .
  34. ^ ab "Sintaxis de expresiones regulares". Documentación de Python 3.5.0 . Fundación de software Python . Archivado desde el original el 18 de julio de 2018 . Consultado el 10 de octubre de 2015 .
  35. ^ SRE: La agrupación atómica (?>...) no es compatible #34627
  36. ^ ab "Clases esenciales: Expresiones regulares: Cuantificadores: Diferencias entre cuantificadores codiciosos, reacios y posesivos". Los tutoriales de Java . Oráculo . Archivado desde el original el 7 de octubre de 2020 . Consultado el 23 de diciembre de 2016 .
  37. ^ "Agrupación atómica". Tutorial de expresiones regulares . Archivado desde el original el 7 de octubre de 2020 . Consultado el 24 de noviembre de 2019 .
  38. ^ Cezar Campeanu; Kai Salomaa y Sheng Yu (diciembre de 2003). "Un estudio formal de expresiones regulares prácticas". Revista Internacional de Fundamentos de la Informática . 14 (6): 1007–1018. doi :10.1142/S012905410300214X. Archivado desde el original el 4 de julio de 2015 . Consultado el 3 de julio de 2015 .Teorema 3 (p.9)
  39. ^ "La coincidencia de expresiones regulares de Perl es NP-Hard". perl.plover.com . Archivado desde el original el 7 de octubre de 2020 . Consultado el 21 de noviembre de 2019 .
  40. ^ Ritchie, DM; Thompson, KL (junio de 1970). Editor de texto QED (PDF) . MM-70-1373-3. Archivado desde el original (PDF) el 3 de febrero de 2015 . Consultado el 5 de septiembre de 2022 .Reimpreso como "Manual de referencia del editor de texto QED", MHCC-004, Murray Hill Computing, Bell Laboratories (octubre de 1972).
  41. ^ ab Wall, Larry (18 de octubre de 1994). "Perl 5: perlre.pod". GitHub .
  42. ^ Lógica errante. "¿Cómo simular anticipaciones y retrospectivas en autómatas de estados finitos?". Intercambio de pilas de informática . Archivado desde el original el 7 de octubre de 2020 . Consultado el 24 de noviembre de 2019 .
  43. ^ Zakharevich, Ilya (19 de noviembre de 1997). "Parche Jumbo Regexp aplicado (con ajustes menores de reparación): Perl/perl5@c277df4". GitHub .
  44. ^ Cox (2007)
  45. ^ Laurikari (2009)
  46. ^ "gnulib/lib/dfa.c". Archivado desde el original el 18 de agosto de 2021 . Consultado el 12 de febrero de 2022 . Si el escáner detecta una transición en la referencia inversa, devuelve una especie de "semiéxito" que indica que la coincidencia deberá verificarse con un comparador de retroceso.
  47. ^ Kearns, Steven (agosto de 2013). "Coincidencia sublineal con autómatas finitos mediante escaneo de sufijo inverso". arXiv : 1308.3822 [cs.DS].
  48. ^ Navarro, Gonzalo (10 de noviembre de 2001). "NR-grep: una herramienta de coincidencia de patrones rápida y flexible" (PDF) . Software: práctica y experiencia . 31 (13): 1265-1312. doi :10.1002/spe.411. S2CID  3175806. Archivado (PDF) desde el original el 7 de octubre de 2020 . Consultado el 21 de noviembre de 2019 .
  49. ^ "travisdowns/poliregex". GitHub . 5 de julio de 2019. Archivado desde el original el 14 de septiembre de 2020 . Consultado el 21 de noviembre de 2019 .
  50. ^ Schmid, Markus L. (marzo de 2019). "Expresiones regulares con referencias inversas: técnicas de coincidencia de tiempo polinómico". arXiv : 1903.05896 [cs.FL].
  51. ^ "Documentación de Vim: patrón". Vimdoc.sourceforge.net. Archivado desde el original el 7 de octubre de 2020 . Consultado el 25 de septiembre de 2013 .
  52. ^ ab "UTS#18 sobre expresiones regulares Unicode, Anexo A: Bloques de caracteres". Archivado desde el original el 7 de octubre de 2020 . Consultado el 5 de febrero de 2010 .
  53. ^ "regex(3) - página del manual de Linux". man7.org . Consultado el 27 de abril de 2022 .
  54. ^ "Biblioteca de expresiones regulares - cppreference.com". es.cppreference.com . Consultado el 27 de abril de 2022 .
  55. ^ "Patrón (Plataforma Java SE 7)". docs.oracle.com . Consultado el 27 de abril de 2022 .
  56. ^ "Expresiones regulares: JavaScript". MDN . Consultado el 27 de abril de 2022 .
  57. ^ "Biblioteca OCaml: Str". v2.ocaml.org . Consultado el 21 de agosto de 2022 .
  58. ^ "perla". perldoc.perl.org . Consultado el 4 de febrero de 2023 .
  59. ^ "PHP: PCRE - Manual". www.php.net . Consultado el 4 de febrero de 2023 .
  60. ^ "re - Operaciones de expresiones regulares". docs.python.org . Consultado el 24 de febrero de 2023 .
  61. ^ "Regex en crates.io". Cajas.io . Archivado desde el original el 29 de noviembre de 2022 . Consultado el 24 de febrero de 2023 .
  62. ^ Horowitz, Bradley (24 de octubre de 2011). "Un barrido de otoño". Blog de Google . Archivado desde el original el 21 de octubre de 2018 . Consultado el 4 de mayo de 2019 .
  63. ^ El carácter 'm' no siempre es necesario para especificar una operación de coincidencia de Perl . Por ejemplo, m/[^abc]/también podría representarse como /[^abc]/. La 'm' solo es necesaria si el usuario desea especificar una operación de coincidencia sin utilizar una barra diagonal como delimitador de expresiones regulares . A veces es útil especificar un delimitador de expresiones regulares alternativo para evitar una " colisión de delimitadores ". Consulte 'perldoc perlre Archivado el 31 de diciembre de 2009 en Wayback Machine ' para obtener más detalles.
  64. ^ Por ejemplo, consulte Java en pocas palabras , p. 213; Secuencias de comandos Python para ciencias computacionales , p. 320; Programación PHP , pág. 106.
  65. ^ Todas las declaraciones if devuelven un valor VERDADERO
  66. ^ Conway, Damián (2005). "Expresiones regulares, final de cadena". Mejores prácticas de Perl . O'Reilly . pag. 240.ISBN _ 978-0-596-00173-5. Archivado desde el original el 7 de octubre de 2020 . Consultado el 10 de septiembre de 2017 .

Referencias

enlaces externos