Escape de las comillas dobles en el parámetro

109

En Unix podría correr myscript '"test"'y lo conseguiría "test".

En Windows cmdobtengo '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.

Bryan Field
fuente
2
Han pasado años desde que toqué una máquina con Windows, pero ¿no funciona el carácter de escape estándar (barra invertida \)? Ej .myscript \"test\"
Gazler
¡No! Obtengo \ test \. Sospecho que se debe a que Windows usa \ en lugar de /, por lo que la barra invertida no se puede usar como escape. Pero realmente no lo sé.
Bryan Field
Idk qué versión de Windows estás usando, pero \ "funciona bien en Windows 7 (Ultimate). Sin embargo, hay otra forma de hacerlo, manejando múltiples comillas (es decir," "" se convierte en "o algo así), pero no puedo averigua cuándo y cómo funciona.
Codesmith
2
posible duplicado de Escaping Double Quotes en Batch Script
sirdank

Respuestas:

22

No puedo reproducir rápidamente los síntomas: si intento myscript '"test"'con un archivo por lotes que myscript.batcontenga solo @echo.%1o incluso @echo.%~1, obtengo todas las citas:'"test"'

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

mousio
fuente
3
Entonces, ¿quizás las respuestas a esta pregunta podrían ayudarlo más?
mousio
2
¡Decir ah! ¡Nunca hubiera imaginado que era wscriptculpa! Déjelo en Windows :)
Bryan Field
4
En realidad, ^ no funcionó para mí, pero \ sí, según esta respuesta: stackoverflow.com/questions/2403647/…
kalenjordan
26
Windows: el sistema operativo en el que el ejecutable se invoca en lugar del shell para realizar el globbing, la expansión de shell y la eliminación de escape de parámetros. Nunca se sabe qué convención, si la hay, honra el ejecutable invocado.
binki
7
Valiosa aportación: blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/… . El símbolo de intercalación es de hecho el carácter de escape elegido para cmd.
Peter - Reincorpora a Monica
198

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 envuelto en grupos entre comillas dobles, espacios separados parámetros:
    program param1 param2 param 3pasarán cuatro parámetros a program.exe:
         param1, param2, param, y 3.
  2. Un grupo entre comillas dobles ignora los espacios como separadores de valor al pasar parámetros a los programas:
    program one two "three and more"pasará tres parámetros a program.exe:
         one, two, y three and more.
  3. Ahora para explicar algo de la confusión:
  4. Grupos que aparecen directamente adyacente al texto no envuelto con comillas dobles unirse en un solo parámetro doble cita:
    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 adyacentes entre sí.
  6. Cualquier comilla doble directamente después de una cita de cierre se trata como (o como parte de) texto sin formato que es adyacente al grupo de comillas dobles, pero solo una comilla doble:
    "Tim says, ""Hi!"""actuará como un parámetro:Tim says, "Hi!"

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

"grupo de comillas dobles abierto
T dentro de "" s
estoy dentro de "" s
m dentro de "" s
    dentro de "" s - el espacio no se separa
s dentro de "" s
un interior "" s
y dentro de "" s
s dentro de "" s
, dentro de "" s
    dentro de "" s - el espacio no se separa
"cerrar grupo de comillas dobles
"la cita sigue directamente más cerca - actúa como texto sin formato:"
H fuera de "" s: se une al grupo adyacente anterior
yo afuera "" s - ...
! afuera "" s - ...
"grupo de comillas dobles abierto
"cerrar grupo de comillas dobles
"la cita sigue directamente más cerca - actúa como texto sin formato:"

Por lo tanto, el texto une efectivamente 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 el cuarto, la cita cerrada sin envolver.

Como puede ver, el grupo de comillas dobles que envuelve nada todavía es necesario ya que, sin él, la siguiente comilla doble abriría un grupo de comillas dobles en lugar de actuar como texto sin formato.

A partir de esto, debe reconocerse que, por lo tanto, dentro y fuera de las comillas, tres comillas dobles actúan como comillas dobles sin formato de texto sin formato:

"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 usar tres comillas como un escape.
Sin embargo, al comprenderlo, puede notar que las cuatro citas al final se pueden reducir a solo dos, ya que técnicamente está agregando otro grupo vacío innecesario de comillas dobles.

Aquí hay algunos ejemplos para cerrarlo:

programa ab REM envía (a) y (b)
programa "" "a" "" REM envía ("a")
programa "" "a b" "" REM envía ("a) y (b")
programa "" "" Hola "" "dijo Mike". REM envía ("Hola", dijo Mike).
programa "" a "" b "" c "" d "" REM envía (abcd) ya que los grupos "" no envuelven nada
programa "hola a" "" comillas "" REM envía (hola a "comillas")
programa "" "" hola mundo "" REM envía ("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 "" REM envía (hola "mundo")

Nota final: no leí nada de esto en ningún tutorial, se me ocurrió todo experimentando. Por lo tanto, mi explicación puede no ser cierta internamente. No obstante, todos los ejemplos anteriores se evalúan como se da, 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
fuente
11
+1, pero tenga en cuenta que este comportamiento depende de la aplicación. En Windows, cada aplicación analiza sus propios parámetros de línea de comando. Creo que el comportamiento que está describiendo es el de la biblioteca C estándar de Microsoft, que creo que también está duplicada por la mayoría de los demás compiladores de Windows C.
Harry Johnston
3
Múltiples errores en su último ejemplo. programa "" "ab" "" -> ("ab"), programa "hola a" "" comillas "" -> (hola a "comillas), programa" "" "hola mundo" "-> (" Hola) (mundo), programa "" "hola" mundo "" -> ("hola) (mundo), programa" "" hola "mundo" "-> (" hola mundo), programa "hola" "" mundo "" - > (hola "mundo)
Thomson
46
... Todo lo que puedo decir es que los archivos por lotes de Windows tienen problemas. Se trata de citas que se escapan , por el amor de Dios; no debería tener que ser una especie de ciencia espacial.
James Ko
4
@JamesKo No podría estar más de acuerdo. El arcano absurdo y la inconsistencia de la línea de comandos de Windows nunca deja de enojarme. ¿Quién diseñó esta basura? ¡Oh, las horas desperdiciadas a lo largo de los años! Unix es tan fácil y tiene mucho sentido en comparación.
Carlos A. Ibarra
24

Prueba esto:

myscript """test"""

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

smwikipedia
fuente
1
Eso no es del todo correcto. Pruébelo myscript """test test"""y no funciona (el primer parámetro se entrega como "test. Actualmente, necesita tres citas: myscript """"test test""la tercera cita al final se puede omitir, sin embargo.
Ignitor
¿Qué sucede si necesito eliminar todas las comillas aquí y colocar el valor del parámetro en una cadena utilizada en un filtro de consulta de selección? Alguien puede ayudar
SFDC_Learner
2
Tal vez no sea acertado para esta pregunta, pero esto me ayudó cuando necesitaba pasar char **argvde mi lanzador C a otro proceso usando funciones como spawno exec. Gracias. :-)
virgo47
2

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 repetía: Una mejor manera de comprender las comillas 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 guía:

Escapa de cada comilla doble "con un símbolo de intercalación ^. Si desea que otros caracteres con significado especial para el shell de comandos de Windows (por ejemplo, <, >, |, &) debe interpretarse como personajes regulares en su lugar, y luego escapar de ellos con un acento circunflejo, también.

Si desea que su programa foo reciba el texto de la línea de comandos "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 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 ""como una comilla doble literal, entonces inicie su programa como

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

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

Un poco más de prueba y error implica que en el estado inicial, se reconoce la redirección (a un archivo o tubería) y un signo de intercalación ^escapa a una comilla doble y el signo de intercalación se elimina de la entrada. En el otro estado, la redirección no se reconoce y un signo de intercalación no escapa a una comilla doble y no se elimina. Vamos a referirnos a estos estados como "afuera" e "adentro", respectivamente.

Si desea redirigir la salida de su comando, entonces el shell de comandos debe estar en el estado externo cuando alcanza 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 todo "a\"b " > out.txta foo como sus argumentos de línea de comando combinados, en lugar de pasar solo "a\"b "y redirigir la salida a out.txt .

foo "a\^"b " > out.txttampoco funcionará, porque el signo 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 funciona es mantener el shell de comandos siempre en el estado externo, porque entonces la redirección funciona.

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

foo "a\"b c"

Entonces foo recibe "a\"b c"como sus argumentos combinados texto y puede interpretarlo como un solo argumento 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 una comilla doble literal y luego especificarlo en su comando, utilizando ^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 el truco. Tratar

myscript \^"test\^"

o, si no necesita redirección,

myscript \"test\"
Louis Strous
fuente
¡GRACIAS! Me estaba golpeando la cabeza contra la pared tratando de ejecutar un vbscript con el texto del indicador de cmd que se repite en el texto del indicador de cmd (heredé esto) y no pude encontrar una manera de escapar de las comillas.
PopeDarren
0

Estoy llamando a powershell desde cmd, y pasando comillas y ninguno de los escapes aquí funcionó. El acento grave funcionó para escapar de las comillas dobles en este profesional de superficie de Win 10.

>powershell.exe "echo la`"" >> test
>type test
la"

A continuación se muestran los resultados que obtuve para que otros personajes escapen de una comilla doble:

la\
la^
la
la~

El uso de otra cita para escapar de una cita resultó en ninguna cita. Como puede ver, los propios caracteres se escribieron, pero no escaparon a las comillas dobles.

Zimba
fuente