2009-08-18 11 views
14

Aquí hay una aplicación Python barebones que simplemente imprime los argumentos de línea de comandos pasados ​​en:Cómo aceptar argumentos de línea de comandos que termina en la barra invertida

import sys 
if __name__ == "__main__": 
    print "Arguments:" 
    for i in range(len(sys.argv)): 
     print "[%s] = %s" % (i, sys.argv[i]) 

Y aquí hay algo de carreras de muestra:

python args.py hello world 
Arguments: 
[0] = args.py 
[1] = hello 
[2] = world 

python args.py "hello world" 
Arguments: 
[0] = args.py 
[1] = hello world 

python args.py "hello\world" 
Arguments: 
[0] = args.py 
[1] = hello\world 

Así muy bien. Pero ahora, cuando fin a cualquier discusión con una barra invertida, Python ahoga en él:

python args.py "hello\world\" 
Arguments: 
[0] = args.py 
[1] = hello\world" 

python args.py "hello\" world "any cpu" 
Arguments: 
[0] = args.py 
[1] = hello" world any 
[2] = cpu 

Soy consciente de Python menos que ideales comportamiento cadena de texto a través del prefijo "r" (link), y parece claro que está aplicando el mismo comportamiento aquí.

Pero en este caso, no tengo control de los argumentos que se me pasan, y no puedo exigir que los argumentos no terminen en una barra invertida. ¿Cómo puedo evitar esta limitación frustrante?

-

Editar: Gracias a los que señaló que este comportamiento no es específico de Python. Parece ser el comportamiento de shell estándar (al menos en Windows, no tengo una Mac en este momento).

Pregunta actualizada: ¿Cómo puedo aceptar los argumentos que terminan en una barra diagonal inversa? Por ejemplo, uno de los argumentos para mi aplicación es una ruta de archivo. No puedo exigir que el cliente me lo envíe sin una barra inclinada invertida, o con la barra invertida escapada. ¿Es esto posible de alguna manera?

+0

¿Qué hace el shell estándar con una barra diagonal inversa? ¿Qué hace un comando estándar como "echo" o "ls" con una barra diagonal inversa? –

+0

Gracias S Lott, tienes razón, cuando hago una consola .NET aplicación para hacer lo mismo, obtengo el mismo comportamiento. Por lo tanto, no es específico de Python. –

+0

No ponga su edición al principio porque las primeras palabras de sus preguntas son el resumen en la lista de preguntas principales: su comentario de edición no es es un buen resumen. –

Respuesta

6

La barra invertida en el extremo se interpreta como el inicio de una secuencia de escape, en este caso un carácter literal de comillas dobles. Tuve un problema similar con el manejo de los parámetros del entorno que contenían una ruta que a veces terminaba con un \ y a veces no.
La solución que se me ocurrió fue insertar siempre un espacio al final de la cadena de ruta al llamar al ejecutable. Mi ejecutable utiliza la ruta del directorio con la barra y un espacio al final, que se ignora. Posiblemente podría recortar la ruta dentro del programa si le causa problemas.

Si% SlashPath% = "hola \"

python args.py "%SlashPath% " world "any cpu" 
Arguments: 
[0] = args.py 
[1] = hello\ 
[2] = world 
[3] = any cpu 

Si% SlashPath% = "hola"

python args.py "%SlashPath% " world "any cpu" 
Arguments: 
[0] = args.py 
[1] = hello 
[2] = world 
[3] = any cpu 

Esperemos que esto le dará algunas ideas de cómo llegar a su problema.

+0

Este problema es totalmente irrelevante para mí ahora, pero me encanta su solución de agregar un espacio y lo tendré en cuenta para el futuro. Gracias. =) –

1

La barra diagonal inversa (\) está escapando al ". Eso es todo. Eso es cómo se supone que debe funcionar.

12

Es probable que el shell trate \ como un carácter de escape, y por lo tanto escapando del personaje. Entonces, el shell envía \" como " (porque cree que está intentando escapar de la comilla doble). La solución es escapar del personaje de escape, así: $ python args.py "hello\world\\".

+0

Up. Además, no es python el que estrangula, es la línea de comandos. Está esperando el final ", sin embargo tienes esc Aipó el "usted grabó. – Havenard

+3

Alternativamente, use comillas simples: bash no hace escapes dentro de cadenas entre comillas simples, por lo que '$ python args.py 'hello world \'' se comporta como se esperaba. –

+0

Gracias mipadi. Por cierto, noté que solo escapaste a la segunda barra invertida, pero parece ser la correcta. –

2

La barra invertida 'escapa' del personaje que la sigue. Esto significa que las comillas de cierre se convierten en una parte del argumento y en realidad no terminan la cadena.

Este es el comportamiento del shell que está utilizando (presumiblemente bash o similar), no Python (aunque también puede escapar caracteres dentro de las cadenas de Python).

La solución es escapar las barras invertidas:

python args.py "hello\world\\" 

Su script Python debe entonces funcionar como se espera que lo haga.

+0

Bueno, la primera barra invertida aparentemente no se debe escapar (ver la publicación anterior de mipadi, no escapa a la primera), pero gracias por señalar que no es específica de Python. –

+0

Supongo que la primera doble barra invertida no es estrictamente requerida en este caso, pero eso es solo porque '\ w' no significa nada para el shell. Si la primera barra seguía una 'n' o' t', terminarías con espacios en blanco no deseados en la cadena. Solo escaparía de ambos cortes para estar un poco más a la defensiva. – harto

+0

No, quiero decir que en realidad da una entrada incorrecta. pitón args.py "hola mundo \\ \\" Argumentos: [0] = args.py [1] = \\ hola mundo \ –

1

Si esto está en Windows, entonces no está utilizando un símbolo del sistema estándar de Windows (o shell). Esto debe ser bash haciendo esto. El símbolo del sistema de Windows no trata la barra diagonal inversa como un carácter de escape (ya que es el separador de ruta de archivo).

extra punto de curiosidades: el carácter citando en símbolos del sistema Windows es símbolo de intercalación:^

+0

Pero está en Windows. Estoy viendo este comportamiento tanto con una aplicación de consola de Python como con una aplicación de consola C# .NET. –

+0

¿Pero qué cáscara estás usando? Puedes usar bash como tu caparazón en Windows. No estoy diciendo que no esté sucediendo, solo quería aclarar que su elección de asuntos de concha. –

5

el parámetro reglas de análisis de Microsoft

Estas son las reglas para analizar una línea de comando que se pasa por CreateProcess() a una programa escrito en C/C++:

  1. Parámetros siempre están separados por un espacio o pestaña (múltiples espacios/pestañas OK)
  2. Si el parámetro no contenga ningún espacios, tabulaciones, o comillas dobles, entonces todos los caracteres en el parámetro son aceptados como es (no hay necesidad de escribir el parámetro entre comillas dobles).
  3. Encierre espacios y las pestañas en un doble citado parte
  4. Una parte comillas dobles puede estar en cualquier lugar dentro de un parámetro
  5. barras invertidas 2n seguido por un " productos n barras invertidas + de inicio/fin doble parte citada
  6. 2n + 1 barras invertidas seguidas por un + una marca cita " productos n barras invertidas literal
  7. n barras invertidas no seguidos por un comilla productos n barras invertidas
  8. Si un cierre "es seguido inmediatamente por otra", la segunda " se acepta literalmente, y se añade a el parámetro (Esta es la regla indocumentado .)

Para una descripción detallada y clara ver http://www.daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULESDOC

+0

Solo hay un documento vacío en ese enlace, ¿puede proporcionar otro enlace a estas reglas de análisis? – cod3monk3y

+0

Parece que movió su sitio web a daviddeley.com. El texto exacto de esta respuesta está incluido allí, así que creo que mi suposición es precisa, y he actualizado el enlace en consecuencia. Estos son detalles muy interesantes. ¡Gracias por publicar! – cod3monk3y

0

Cuando el usuario pasa su función una cadena "hola \", independientemente de cuál fue su intención, enviaron la cadena de hola ", como si un usuario pasara un archivo como" temp \ table "lo que realmente tienen tipeado, intencionalmente o no, es "temporal" (pestaña en el medio).

Dicho esto, una solución a este problema significa que si un usuario ingresa "temp \ table" y honestamente significa "temp able", va a procesar esto en "temp \ table" y ahora tiene programáticamente destruyó la entrada de los usuarios.

Con esta advertencia en mente, si aún desea hacer esto, puede buscar la representación de cadena de estos caracteres escapados y reemplazarlos. Como un ejemplo muy sencillo, algo como esto:

def allow_tabs(str_w_tab): 
    str_w_tab.replace('\t','\\t') 
    print str_w_tab 

Ahora bien, si desea manejar todos los demás caracteres de escape, que tendrá que hacer algo similar para cada uno. En cuanto a poder hacer esto para el ejemplo: "hola", el usuario le pasó la cadena de hola ", y si lo intentaron o no, nunca cerraron la comilla doble, así que esto es lo que ve su programa.

Cuestiones relacionadas