Escape de comillas dobles en el parámetro

Resuelto 700 Software asked hace 13 años • 6 respuestas

En Unix podría ejecutar myscript '"test"'y obtendría "test".

En Windows cmdme sale 'test'.

¿Cómo puedo pasar comillas dobles como parámetro? Me gustaría saber cómo hacer esto manualmente desde una cmdventana para no tener que escribir un programa para probarlo.

700 Software avatar Oct 14 '11 04:10 700 Software
Aceptado

Otra forma de escapar de las comillas (aunque probablemente no sea preferible), que he encontrado que se usa en ciertos lugares, es usar múltiples comillas dobles . Con el fin de hacer legible el código de otras personas, lo explicaré.

Aquí hay un conjunto de reglas básicas:

  1. Cuando no están entre comillas dobles, los espacios separan los parámetros:
    program param1 param2 param 3pasarán cuatro parámetros a program.exe:
         param1, param2, paramy 3.
  2. Un grupo entre comillas dobles ignora los espacios como separadores de valores al pasar parámetros a programas:
    program one two "three and more"pasará tres parámetros a program.exe:
         one, twoy three and more.
  3. Ahora para explicar algo de la confusión:
  4. Los grupos entre comillas dobles que aparecen directamente adyacentes al texto no entre comillas dobles se unen en un parámetro:
    hello"to the entire"worldactúa como un parámetro: helloto the entireworld.
  5. Nota: La regla anterior NO implica que dos grupos entre comillas dobles puedan aparecer directamente uno al lado del otro.
  6. Cualquier comilla doble que sigue directamente a una comilla de cierre se trata como (o como parte de) texto sin formato adyacente al grupo de comillas dobles, pero solo una comilla doble:
    "Tim says, ""Hi!"""actuará como un parámetro:Tim says, "Hi!"

Por lo tanto, existen tres tipos diferentes de comillas dobles: comillas que abren, comillas que cierran y comillas que actúan como texto sin formato.
Aquí está el desglose de esa última línea confusa:

" abrir grupo de comillas dobles
T dentro de "" s
yo dentro de "" s
m dentro de "" s
    dentro de "" s - el espacio no se separa
está dentro de "" s
una "" interior
y dentro de "" s
está dentro de "" s
, dentro de "" s
    dentro de "" s - el espacio no se separa
" cerrar grupo entre comillas dobles
"La cita sigue directamente al detalle; actúa como texto sin formato: "
H fuera de ""s: se une al grupo adyacente anterior
Yo fuera de ""s - ...
! fuera de "" s - ...
" abrir grupo de comillas dobles
" cerrar grupo de comillas dobles
"La cita sigue directamente al detalle; actúa como texto sin formato: "

Así, el texto efectivamente une cuatro grupos de caracteres (uno sin nada, sin embargo):
Tim says,  es el primero, envuelto para escapar de los espacios
"Hi!; es el segundo, no envuelto (no hay espacios)
 ; es el tercero, un grupo de comillas dobles que no envuelve nada.
"es la cuarta, la cita de cierre sin envolver.

Como puede ver, el grupo de comillas dobles que envuelve nada sigue siendo necesario ya que, sin él, las siguientes comillas dobles abrirían un grupo de comillas dobles en lugar de actuar como texto sin formato.

A partir de esto, debería ser reconocible que, por lo tanto, dentro y fuera de las comillas, tres comillas dobles actúan como una comilla doble sin escape en texto plano:

"Tim le dijo: ""¿Qué ha estado pasando últimamente?""""

se imprimirá Tim said to him, "What's been happening lately?"como se esperaba. Por lo tanto, siempre se pueden utilizar tres comillas de forma fiable como escape.
Sin embargo, al comprenderlo, puede notar que las cuatro comillas al final se pueden reducir a solo dos, ya que técnicamente agrega otro grupo de comillas dobles vacío innecesario.

Aquí hay algunos ejemplos para cerrarlo:

programa ab REM envía (a) y (b)
programa """a""" envía REM ("a")
programa """a b""" Envíos REM ("a) y (b")
programa """"Hola","" dijo Mike." REM envía ("Hola", dijo Mike).
programa ""a""b""c""d"" envía REM (abcd) ya que los "" grupos no envuelven nada
programa "hola a """quotes"" envía REM (hola a "quotes")
programa """"hola mundo"" envía REM ("hola mundo")
programa """hola" mundo"" REM envía ("hola mundo")
programa """hola "mundo"" REM envía ("hola) y (mundo")
programa "hola ""mundo""" REM envía (hola "mundo")
programa "hola """mundo"" envía REM (hola "mundo")

Nota final: no leí nada de esto en ningún tutorial; todo se me ocurrió experimentando. Por lo tanto, mi explicación puede no ser cierta internamente. No obstante, todos los ejemplos anteriores se evalúan como dados, validando así (pero no probando) mi teoría.

Probé esto en Windows 7, 64 bits usando solo llamadas *.exe con paso de parámetros (no *.bat, pero supongo que funciona igual).

Codesmith avatar Mar 07 '2013 02:03 Codesmith

No puedo reproducir rápidamente los síntomas: si lo intento myscript '"test"'con un archivo por lotes myscript.batque contiene just @echo.%1o even @echo.%~1, obtengo todas las comillas:'"test"'

Quizás puedas probar el carácter de escape ^así: myscript '^"test^"'?

mousio avatar Oct 13 '2011 21:10 mousio

Prueba esto:

myscript """test"""

""escape a un solo" en el parámetro.

smwikipedia avatar Aug 14 '2014 13:08 smwikipedia

El segundo documento citado por Peter Mortensen en su comentario sobre la respuesta de Codesmith me dejó las cosas mucho más claras. Ese documento fue escrito por windowsinspired.com. El enlace se repetía: Una mejor manera de comprender las citas y el escape de los argumentos de la línea de comandos de Windows .

Un poco más de prueba y error conduce a la siguiente directriz:

Escapa cada comilla doble "con un signo de intercalación ^. Si desea que otros caracteres con un significado especial para el shell de comandos de Windows (por ejemplo, , <, ) se interpreten como caracteres normales, escríbalos también con un signo de intercalación.>|&

Si desea que su programa foo reciba el texto de la línea de comando "a\"b c" > dy redirija su salida al archivo out.txt , inicie su programa de la siguiente manera desde el shell de comandos de Windows:

foo ^"a\^"b c^" ^> d > out.txt

Si foo se interpreta \"como una comilla doble literal y espera que las comillas dobles sin escape delimiten los argumentos que incluyen espacios en blanco, entonces foo interpreta que el comando especifica un argumento a"b c, un argumento >y un argumento d.

Si, en cambio, foo interpreta una comilla doble doble ""como una comilla doble literal, inicie su programa como

foo ^"a^"^"b c^" ^> d > out.txt

La idea clave del documento citado es que, en el shell de comandos de Windows, una comilla doble sin escape activa el cambio entre dos estados posibles.

Un poco de prueba y error adicional implica que en el estado inicial, se reconoce la redirección (a un archivo o canalización), se ^escapa un símbolo de intercalación entre comillas dobles y se elimina de la entrada. En el otro estado, no se reconoce la redirección y un signo de intercalación no escapa a una comilla doble y no se elimina. Nos referiremos a estos estados como "exterior" e "interior", respectivamente.

Si desea redirigir la salida de su comando, entonces el shell del comando debe estar en el estado externo cuando llegue a la redirección, por lo que debe haber un número par de comillas dobles sin escape (por intercalación) antes de la redirección. foo "a\"b " > out.txtno funcionará: el shell de comandos pasa el valor completo "a\"b " > out.txta foo como argumentos combinados de la línea de comandos, en lugar de pasar solo "a\"b "y redirigir la salida a out.txt .

foo "a\^"b " > out.txttampoco funcionará porque el símbolo de intercalación ^se encuentra en el estado interno donde es un carácter ordinario y no un carácter de escape, por lo que "a\^"b " > out.txtse pasa a foo .

La única forma en que (con suerte) siempre funcione es mantener el shell de comandos siempre en el estado externo, porque entonces la redirección funciona.

Si no necesita redirección (u otros caracteres con significado especial para el shell de comandos), puede prescindir de los signos de intercalación. Si foo se interpreta \"como una comilla doble literal, entonces puedes llamarlo como

foo "a\"b c"

Luego foo recibe "a\"b c"como argumento combinado texto y puede interpretarlo como un argumento único igual a a"b c.

Ahora, finalmente, a la pregunta original. myscript '"test"'llamado desde el shell de comandos de Windows pasa '"test"'a myscript . Aparentemente myscript interpreta las comillas simples y dobles como delimitadores de argumentos y las elimina. Debe averiguar qué acepta myscript como comilla doble literal y luego especificarlo en su comando, usando ^para escapar cualquier carácter que tenga un significado especial para el shell de comandos de Windows. Dado que myscripttambién está disponible en Unix, quizás \"funcione. Intentar

myscript \^"test\^"

o, si no necesita redirección,

myscript \"test\"
Louis Strous avatar May 01 '2019 16:05 Louis Strous