Escape de comillas dobles en el parámetro
En Unix podría ejecutar myscript '"test"'
y obtendría "test"
.
En Windows cmd
me sale 'test'
.
¿Cómo puedo pasar comillas dobles como parámetro? Me gustaría saber cómo hacer esto manualmente desde una cmd
ventana para no tener que escribir un programa para probarlo.
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:
- Cuando no están entre comillas dobles, los espacios separan los parámetros:
program param1 param2 param 3
pasarán cuatro parámetros aprogram.exe
:
param1
,param2
,param
y3
. - 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 aprogram.exe
:
one
,two
ythree and more
.
Ahora para explicar algo de la confusión:
- 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"world
actúa como un parámetro:helloto the entireworld
.
Nota: La regla anterior NO implica que dos grupos entre comillas dobles puedan aparecer directamente uno al lado del otro.
- 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).
No puedo reproducir rápidamente los síntomas: si lo intento myscript '"test"'
con un archivo por lotes myscript.bat
que contiene just @echo.%1
o even @echo.%~1
, obtengo todas las comillas:'"test"'
Quizás puedas probar el carácter de escape ^
así: myscript '^"test^"'
?
Prueba esto:
myscript """test"""
""escape a un solo" en el parámetro.
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" > d
y 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.txt
no funcionará: el shell de comandos pasa el valor completo "a\"b " > out.txt
a 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.txt
tampoco 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.txt
se 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 myscript
también está disponible en Unix, quizás \"
funcione. Intentar
myscript \^"test\^"
o, si no necesita redirección,
myscript \"test\"