¿Por qué los literales de cadena sin procesar de Python no pueden terminar con una barra diagonal inversa simple?

StackOverflow https://stackoverflow.com/questions/647769

Pregunta

Técnicamente, cualquier número impar de barras invertidas, como se describe en los documentos .

>>> r'\'
  File "<stdin>", line 1
    r'\'
       ^
SyntaxError: EOL while scanning string literal
>>> r'\\'
'\\\\'
>>> r'\\\'
  File "<stdin>", line 1
    r'\\\'
         ^
SyntaxError: EOL while scanning string literal

Parece que el analizador podría tratar las barras invertidas en cadenas sin procesar como caracteres normales (¿no es eso de lo que se tratan las cadenas sin procesar?), pero probablemente me estoy perdiendo algo obvio. TIA!

¿Fue útil?

Solución

La razón se explica en la parte de esa sección que destaqué en negrita:

  

Las comillas de cadena se pueden escapar con un   barra invertida, pero la barra invertida permanece   en la cuerda por ejemplo, r " \ " " es un   literal de cadena válido que consta de dos   personajes: una barra invertida y un doble   citar; r " \ " no es una cadena válida   literal (incluso una cadena sin procesar no puede terminar   en un número impar de barras invertidas).   Específicamente, una cadena sin procesar no puede terminar   en una sola barra invertida (ya que   barra invertida escaparía a lo siguiente   personaje de cita). Tenga en cuenta también que un   barra invertida simple seguida de una nueva línea   se interpreta como esos dos personajes   como parte de la cadena, no como una línea   continuación.

Por lo tanto, las cadenas sin formato no son 100% sin formato, todavía hay un procesamiento rudimentario de barra invertida.

Otros consejos

Todo el concepto erróneo acerca de las cadenas sin formato de Python es que la mayoría de la gente piensa que la barra invertida (dentro de una cadena sin formato) es solo un carácter normal como todos los demás. No lo es. La clave para entender es la secuencia del tutorial de esta pitón:

  

Cuando hay un prefijo ' r ' o ' R ', un carácter que sigue a un   la barra invertida se incluye en la cadena sin cambios, y todos   las barras invertidas se dejan en la cadena

Por lo tanto, cualquier carácter que sigue a una barra diagonal inversa es parte de una cadena sin formato. Una vez que el analizador ingresa una cadena sin procesar (no unicode) y encuentra una barra invertida, sabe que hay 2 caracteres (una barra invertida y un carácter a continuación).

De esta manera:

  

r'abc \ d ' comprende a, b, c, \, d

     

r'abc \ 'd' comprende a, b, c, \, ', d

     

r'abc \ '' comprende a, b, c, \, '

y:

  

r'abc \ ' comprende a, b, c, \,' pero no hay una cita final ahora.

El último caso muestra que, según la documentación, ahora un analizador no puede encontrar la cotización de cierre ya que la última qoute que ve arriba es parte de la cadena, es decir. la barra invertida no puede ser la última aquí, ya que 'devorará' el cierre de cadena de caracteres.

¡Así son las cosas! ¡Lo veo como uno de esos pequeños defectos en Python!

No creo que haya una buena razón para ello, pero definitivamente no está analizando; es realmente fácil analizar cadenas sin procesar con \ como último carácter.

El problema es que si permites que \ sea el último carácter de una cadena sin formato, no podrás poner " dentro de una cadena cruda. Parece que Python se fue permitiendo '' en lugar de permitir \ como último carácter.

Sin embargo, esto no debería causar ningún problema.

Si le preocupa no poder escribir fácilmente parches de carpetas de Windows como c: \ mypath \ , no se preocupe, ya que puede representarlos como r " C: \ mypath " y, si necesita agregar un nombre de subdirectorio, no lo haga con concatenación de cadenas, ¡de todos modos no es la forma correcta de hacerlo! use os.path.join

>>> import os
>>> os.path.join(r"C:\mypath", "subfolder")
'C:\\mypath\\subfolder'

Otro truco es usar chr (92) ya que se evalúa como " \ " ;.

Recientemente tuve que limpiar una cadena de barras invertidas y lo siguiente hizo el truco:

CleanString = DirtyString.replace(chr(92),'')

Me doy cuenta de que esto no se ocupa del " por qué " pero el hilo atrae a muchas personas que buscan una solución a un problema inmediato.

Para que pueda finalizar una cadena sin procesar con una barra inclinada, le sugiero que use este truco:

>>> print r"c:\test"'\\'
test\

Desde \ " está permitido dentro de la cadena sin formato. Entonces no se puede usar para identificar el final de la cadena literal.

¿Por qué no dejar de analizar el literal de cadena cuando encuentra el primer " ;?

Si ese fuera el caso, entonces \ " no se permitiría dentro de la cadena literal. Pero lo es.

La razón por la cual r '\' es sintácticamente incorrecto es que, aunque la expresión de cadena es sin formato, las comillas utilizadas (simple o doble) siempre deben ser eliminadas, ya que marcarían el final de la citar lo contrario. Entonces, si desea expresar una comilla simple dentro de una cadena entre comillas simples, no hay otra manera que usar \ '. Lo mismo se aplica para las comillas dobles.

Pero podrías usar:

'\\'

Otro usuario que desde entonces eliminó su respuesta (no estoy seguro de si desea que se les acredite) sugirió que los diseñadores del lenguaje Python podrían simplificar el diseño del analizador utilizando las mismas reglas de análisis y expandiendo los caracteres escapados a forma cruda como una ocurrencia tardía (si el literal se marcó como crudo).

Pensé que era una idea interesante y la estoy incluyendo como wiki comunitaria para la posteridad.

Viniendo de C, es bastante claro para mí que un solo \ funciona como carácter de escape, lo que le permite poner caracteres especiales como líneas nuevas, pestañas y comillas en cadenas.

Eso de hecho no permite \ como último personaje ya que escapará del " y hacer que el analizador se ahogue. Pero como se señaló anteriormente, \ es legal.

  

A pesar de su función, incluso una cadena sin procesar no puede terminar en una sola   barra diagonal inversa, porque la barra diagonal inversa escapa a la siguiente cita   carácter: aún debe escapar del carácter de cita circundante para   incrustarlo en la cuerda. Es decir, r '' ... \ '' no es una cadena válida   literal: una cadena sin formato no puede terminar en un número impar de barras invertidas.
  Si necesita finalizar una cadena sin procesar con una barra invertida simple, puede usar   dos y cortar el segundo.

algunos consejos:

1) si necesita manipular la barra diagonal inversa para la ruta, el módulo estándar de Python os.path es su amigo. por ejemplo:

  

os.path.normpath ('c: / folder1 /')

2) si desea construir cadenas con barra invertida PERO sin barra invertida al FINAL de su cadena, entonces la cadena sin procesar es su amigo (use el prefijo 'r' antes de su cadena literal). por ejemplo:

r'\one \two \three'

3) si necesita anteponer una cadena en una variable X con una barra invertida, puede hacer esto:

X='dummy'
bs=r'\ ' # don't forget the space after backslash or you will get EOL error
X2=bs[0]+X  # X2 now contains \dummy

4) si necesita crear una cadena con una barra diagonal inversa al final, combine los consejos 2 y 3:

voice_name='upper'
lilypond_display=r'\DisplayLilyMusic \ ' # don't forget the space at the end
lilypond_statement=lilypond_display[:-1]+voice_name

ahora lilypond_statement contiene " \ DisplayLilyMusic \ upper "

¡viva Python! :)

n3on

Encontré este problema y encontré una solución parcial que es buena para algunos casos. A pesar de que Python no puede finalizar una cadena con una sola barra diagonal inversa, se puede serializar y guardar en un archivo de texto con una sola barra diagonal inversa al final. Por lo tanto, si lo que necesita es guardar un texto con una barra invertida en su computadora, es posible:

x = 'a string\\' 
x
'a string\\' 

# Now save it in a text file and it will appear with a single backslash:

with open("my_file.txt", 'w') as h:
    h.write(x)

Por cierto, no funciona con json si lo vuelcas usando la biblioteca json de python.

Finalmente, trabajo con Spyder, y noté que si abro la variable en el editor de texto de la araña haciendo doble clic en su nombre en el explorador de variables, aparece una barra invertida y se puede copiar al portapapeles de esa manera (No es muy útil para la mayoría de las necesidades, pero tal vez para algunos ...).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top