¿Qué es exactamente una "expresión regular de cadena raw" y cómo se puede utilizar?


De la documentación de python sobre regex , con respecto al carácter '\':

La solución es usar la notación de cadena raw de Python para patrones de expresión; las barras invertidas no se manejan de ninguna manera especial en un literal de cadena con el prefijo 'r'. Así que r"\n" es una cadena de dos caracteres contiene '\' y 'n', mientras que "\n" es una cadena de un carácter contiene una nueva línea. Por lo general, los patrones se expresarán en Python código usando esta cadena raw notación.

¿Qué es esta notación de cadena sin procesar? Si utiliza un formato de cadena raw, ¿significa que "*" se toma como un carácter literal en lugar de un indicador de cero o más? Eso obviamente no puede estar bien, o de lo contrario regex perdería completamente su poder. Pero si es una cadena raw, ¿cómo reconoce caracteres de nueva línea si "\n" es literalmente una barra invertida y un "n"?

No entiendo.

Editar por recompensa:

Estoy tratando de entender cómo una expresión regular de cadena sin procesar coincide con nuevas líneas, pestañas y conjuntos de caracteres, por ejemplo, \w para palabras o \d para dígitos o todo lo demás, si los patrones de cadena sin procesar no reconocen las barras invertidas como algo más que caracteres ordinarios. Me vendrían muy bien algunos buenos ejemplos.

Author: Yyttsa, 2012-10-13

5 answers

La respuesta de Zarkonnen responde a tu pregunta, pero no directamente. Déjame tratar de ser más directo, y ver si puedo conseguir la recompensa de Zarkonnen.

Quizás encuentre esto más fácil de entender si deja de usar los términos "regex de cadena sin procesar" y "patrones de cadena sin procesar". Estos términos combinan dos conceptos separados: las representaciones de una cadena particular en el código fuente de Python, y qué expresión regular representa esa cadena.

De hecho, es útil pensar en estos dos lenguajes de programación diferentes, cada uno con su propia sintaxis. El lenguaje Python tiene código fuente que, entre otras cosas, construye cadenas con ciertos contenidos, y llama al sistema de expresión regular. El sistema de expresión regular tiene código fuente que reside en objetos string y coincide con strings. Ambos lenguajes usan barra invertida como un carácter de escape.

Primero, entienda que una cadena es una secuencia de caracteres (es decir, bytes o puntos de código Unicode; la distinción no importa mucho aquí). Hay muchas maneras de representar una cadena en el código fuente de Python. Una cadena sin procesar es simplemente una de estas representaciones. Si dos representaciones dan como resultado la misma secuencia de caracteres, producen un comportamiento equivalente.

Imagine una cadena de 2 caracteres, que consiste en el carácter barra invertidaseguido del carácter n. Si sabe que el valor del carácter para barra invertida es 92, y para n es 110, entonces esta expresión genera nuestra cadena:

s = chr(92)+chr(110)
print len(s), s

2 \n

La notación convencional de cadena de Python "\n" no genera esta cadena. En su lugar, genera una cadena de un carácter con un carácter de nueva línea. El Python docs 2.4.1. Literales de cuerda diga :" El carácter de barra invertida ( \ ) se usa para escapar caracteres que de otra manera tienen un significado especial, como nueva línea, barra invertida en sí, o el carácter de comilla."

s = "\n"
print len(s), s

1 
 

(Tenga en cuenta que la nueva línea no es visible en este ejemplo, pero si miras con cuidado, verás una línea en blanco después del"1".)

Para obtener nuestra cadena de dos caracteres, tenemos que usar otro carácter barra invertida para escapar del significado especial del carácter original barra invertida :

s = "\\n"
print len(s), s

2 \n

¿Qué pasa si desea representar cadenas que tienen muchos caracteres barra invertida en ellas? Python docs 2.4.1. Literales de cuerda continuar, " Los literales de cadena opcionalmente pueden tener el prefijo de una letra 'r' o 'R'; estas cadenas se llaman cadenas raw y usan diferentes reglas para interpretar secuencias de escape de barra invertida."Aquí está nuestra cadena de dos caracteres, usando la representación de cadena cruda:

s = r"\n"
print len(s), s

2 \n

Así que tenemos tres representaciones de cadenas diferentes, todas dando la misma cadena, o secuencia de caracteres:{[17]]}

print chr(92)+chr(110) == "\\n" == r"\n"
True

Ahora, pasemos a las expresiones regulares. Python docs, 7.2. re - Operaciones de expresión regular dice: "Las expresiones regulares usan el carácter de barra invertida ( ' \ ' ) para indicar formas especiales o para permitir que se utilicen caracteres especiales sin invocar su significado especial. Esto choca con el uso de Python del mismo carácter para el mismo propósito en literales de cadena..."

Si desea un objeto de expresión regular de Python que coincida con un carácter de nueva línea, entonces necesita una cadena de 2 caracteres, que consiste en el carácter barra invertida seguido del carácter n. Todas las siguientes líneas de código prog a un objeto de expresión regular que reconoce un carácter de nueva línea:

prog = re.compile(chr(92)+chr(110))
prog = re.compile("\\n")
prog = re.compile(r"\n")

Entonces, ¿por qué "Normalmente los patrones se expresarán en código Python usando esta notación de cadena sin procesar."? Porque las expresiones regulares son con frecuencia cadenas estáticas, que se representan convenientemente como literales de cadena. Y de las diferentes notaciones literales de cadena disponibles, las cadenas raw son una opción conveniente, cuando la expresión regular incluye una barra invertida caracter.

Preguntas

P: ¿qué pasa con la expresión re.compile(r"\s\tWord")? A: Es más fácil de entender separando la cadena de la compilación de expresiones regulares, y entendiéndolas por separado.

s = r"\s\tWord"
prog = re.compile(s)

La cadena s contiene ocho caracteres: a barra invertida, an s, a barra invertida, a t, y luego cuatro caracteres Word.

Q: Qué sucede con la pestaña y el espacio ¿personajes? A: A nivel del lenguaje Python, string s no tiene tab y space carácter. Comienza con cuatro caracteres: barra diagonal inversa, s, barra diagonal inversa, t . El sistema de expresiones regulares, mientras tanto, trata esa cadena como código fuente en el lenguaje de expresiones regulares, donde significa " coincidir con una cadena que consiste en un carácter de espacio en blanco, un carácter de tabulación y los cuatro caracteres Word.

P: ¿Cómo se emparejan si eso se está tratando como backlash-s y backslash-t? A: Tal vez la pregunta sea más clara si las palabras 'tú' y 'eso' se hacen más específicas: ¿cómo coincide el sistema de expresiones regulares con las expresiones backlash-s y backslash-t? Como 'cualquier carácter de espacio en blanco 'y como'tab carácter'.

Q: ¿O qué pasa si tiene la cadena de 3 caracteres barra invertida-n-nueva línea? A : En Python lenguaje, la cadena de 3 caracteres backslash-n-newline se puede representar como cadena convencional "\\n\n", o raw más cadena convencional r"\n" "\n", o de otras maneras. El sistema de expresiones regulares coincide con la cadena de 3 caracteres barra invertida-n-nueva línea cuando encuentra dos caracteres consecutivos nueva línea.

N.B. Todos los ejemplos y referencias de documentos son a Python 2.7.

Update : Incorporated clarifications from answers of @ Vladislav Zorov and @m. buettner, and de la pregunta de seguimiento de @ Aerovistae.

 50
Author: Jim DeLaHunt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-19 20:29:28

La mayoría de estas preguntas tienen muchas palabras y tal vez sea difícil encontrar la respuesta a su pregunta específica.

Si usa una cadena regular y pasa un patrón como "\t" al analizador de expresiones regulares, Python traducirá ese literal en un búfer con el byte de tabulación (0x09).

Si usas una cadena raw y pasas un patrón como r"\t" al analizador de expresiones regulares, Python no hace ninguna interpretación, y crea un búfer con dos bytes en él: '\ ' y 't'. (0x5c, 0x74).

El analizador de expresiones REGULARES sabe qué hacer con la secuencia '\t' matches lo compara con una pestaña. También sabe qué hacer con el carácter 0x09 that que también coincide con una pestaña. En su mayor parte, los resultados serán indistinguibles.

Así que la clave para entender lo que está sucediendo es reconocer que hay dos analizadores que se emplean aquí. El primero es el analizador de Python, y traduce el literal de cadena (o literal de cadena raw) en una secuencia de bytes. El el segundo es el analizador de expresiones regulares de Python, y convierte una secuencia de bytes en una expresión regular compilada.

 9
Author: Geoff Gerrietts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-13 15:00:07

Parece estar luchando con la idea de que una expresión regular no es parte de Python, sino que es un lenguaje de programación diferente con su propio analizador y compilador. Las cadenas raw le ayudan a obtener el" código fuente " de una expresión regular de forma segura al analizador de expresiones regulares, que luego asignará significado a secuencias de caracteres como \d, \w, \n, etc...

El problema existe porque Python y las expresiones regulares usan \ como carácter de escape, lo cual es, por cierto, una coincidencia-hay lenguajes con otros escape personajes (como "`n" para una nueva línea, pero incluso allí, tienes que usar "\n" en Regex). La ventaja es que no es necesario diferenciar entre cadenas raw y no raw en estos idiomas, no intentarán convertir el texto y carnicearlo, porque reaccionan a diferentes secuencias de escape.

 3
Author: Vladislav Zorov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-12 17:58:46

El problema con el uso de una cadena normal para escribir expresiones regulares que contienen un \ es que termina teniendo que escribir \\ para cada \. Así que los literales de cadena "stuff\\things" y r"stuff\things" producen la misma cadena. Esto resulta especialmente útil si desea escribir una expresión regular que coincida con barras invertidas.

Usando cadenas normales, una expresión regular que coincida con la cadena \ sería "\\\\"!

¿Por qué? Porque tenemos que escapar \ dos veces: una vez para la sintaxis de las expresiones regulares, y una vez para la sintaxis de cadena.

Puedes usar comillas triples para incluir nuevas líneas, así:

r'''stuff\
things'''

Tenga en cuenta que, por lo general, python trataría \-newline como una continuación de línea, pero este no es el caso en cadenas sin procesar. También tenga en cuenta que las barras invertidas todavía escapan las comillas en las cadenas sin procesar, pero se dejan en sí mismas. Así que el literal de cadena raw r"\"" produce la cadena \". Esto significa que no puede terminar un literal de cadena raw con una barra invertida.

Ver el léxico sección de análisis de la documentación de Python para más información.

 2
Author: Zarkonnen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-02 21:30:35

La sección correspondiente del manual de Python ("Literales de cadena y Bytes") tiene una explicación clara de los literales de cadena sin procesar:

Tanto los literales de cadena como los bytes pueden ir prefijados opcionalmente con un letra ' r 'o' R'; tales cadenas se llaman cadenas crudas y tratan barras invertidas como caracteres literales. Como resultado, en literales de cadena, Los escapes' \U 'y' \u ' en cadenas raw no son tratados especialmente. Dar ese Python 2.los literales unicode raw de x se comportan de manera diferente a Python 3.x es el La sintaxis ' ur ' no está soportada.

Nuevo en la versión 3.3: El prefijo' rb ' de los bytes literales sin procesar ha sido añadido como sinónimo de 'br'.

Nuevo en la versión 3.3: Soporte para unicode legacy literal (u'value') fue reintroducido para simplificar el mantenimiento de dual Python 2.x y 3.x bases de código. Ver PEP 414 para más información.

En cadenas entrecomilladas triples, se permiten nuevas líneas y comillas no grabadas (y se conservan), excepto que tres citas sin escaparse en una fila terminar la cadena. (Una "cita" es el carácter utilizado para abrir el string, i.e. either 'or".)

A menos que esté presente un prefijo 'r' o 'R', las secuencias de escape en cadenas se interpretan de acuerdo con reglas similares a las utilizadas por el Estándar C. Las secuencias de escape reconocidas son:

Secuencia de escape Que significa Notas

\barra invertida de nueva línea y nueva línea ignorada
\ Backslash ()
\' Comilla simple (')
\" Comilla doble (")
\ una campana ASCII (BEL)
\b ASCII Retroceso (BS)
\ f ASCII Formfeed (FF)
\n ASCII Linefeed (LF)
\ r Retorno de carro ASCII (CR)
\ t ASCII Horizontal Tab (TAB) \v Pestaña vertical ASCII (VT)
\ooo Carácter con valor octal ooo (1,3)
\xhh Carácter con valor hexadecimal hh (2,3)

Las secuencias de escape solo reconocidas en literales de cadena son:

Secuencia de escape Que significa Notas \N{nombre} Base de datos Unicode (4) \ uxxxx Carácter con valor hexadecimal de 16 bits xxxx (5) \Uxxxxxxxx Carácter con valor hexadecimal de 32 bits xxxxxxxx (6)

Notas:

  1. Como en el estándar C, se aceptan hasta tres dígitos octales.

  2. A diferencia del estándar C, se requieren exactamente dos dígitos hexadecimales.

  3. En un byte literal, los escapes hexadecimales y octales denotan el byte con el valor dado. En un literal de cadena, estos escapes denotan un Carácter Unicode con el valor dado.

  4. Cambiado en la versión 3.3: Se ha añadido soporte para alias de nombre [1].

  5. Las unidades de código individuales que forman partes de un par sustituto se pueden codificar usando esta secuencia de escape. Exactamente cuatro dígitos hexadecimales son requerir.

  6. Cualquier carácter Unicode se puede codificar de esta manera, pero los caracteres fuera del Plano Multilingüe Básico (BMP) se codificarán utilizando un par sustituto si Python se compila para usar unidades de código de 16 bits (el predeterminado). Exactamente ocho hex se requieren dígitos.

A diferencia del estándar C, todas las secuencias de escape no reconocidas se dejan en el cadena sin cambios, es decir, la barra invertida se deja en la cadena. (Este el comportamiento es útil al depurar: si una secuencia de escape está mal escrita, la salida resultante se reconoce más fácilmente como rota.) Es también importante tener en cuenta que las secuencias de escape solo se reconocen en cadena los literales entran en la categoría de escapes no reconocidos para bytes literal.

Incluso en una cadena sin procesar, las comillas de cadena se pueden escapar con una barra invertida, pero la barra invertida permanece en la cadena; por ejemplo, r " \ "" es una cadena literal que consta de dos caracteres: una barra invertida y una doble quote; r " \ " no es un literal de cadena válido (incluso una cadena sin procesar no puede terminar en un número impar de barras invertidas). Específicamente, una cadena raw no puede terminar en una sola barra invertida (ya que la barra invertida siguiente carácter de cita). Tenga en cuenta también que una sola barra invertida seguir por una nueva línea se interpreta como esos dos caracteres como parte de la cadena, no como continuación de línea.

 1
Author: Lorenzo Gatti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-14 16:05:34