Escapar de cotizaciones dobles en un script por lotes


91

¿Cómo haría para reemplazar todas las comillas dobles en los parámetros de mi archivo por lotes con comillas dobles de escape? Este es mi archivo por lotes actual, que expande todos sus parámetros de línea de comando dentro de la cadena:

@echo off
call bash --verbose -c "g++-linux-4.1 %*"

Luego usa esa cadena para hacer una llamada al bash de Cygwin, ejecutando un compilador cruzado de Linux. Desafortunadamente, recibo parámetros como estos pasados ​​a mi archivo por lotes:

"launch-linux-g++.bat" -ftemplate-depth-128 -O3 -finline-functions 
-Wno-inline -Wall  -DNDEBUG   -c 
-o "C:\Users\Me\Documents\Testing\SparseLib\bin\Win32\LinuxRelease\hello.o" 
"c:\Users\Me\Documents\Testing\SparseLib\SparseLib\hello.cpp"

Donde la primera cita alrededor de la primera ruta pasada es terminar prematuramente la cadena que se pasa a GCC y pasar el resto de los parámetros directamente a bash (que falla espectacularmente).

Me imagino que si puedo concatenar los parámetros en una sola cadena y luego escapar de las comillas, debería funcionar bien, pero tengo dificultades para determinar cómo hacerlo. ¿Alguien sabe?

Respuestas:


103

El carácter de escape en los scripts por lotes es ^. Pero para cadenas entre comillas dobles, duplique las comillas:

"string with an embedded "" character"

5
duplicar las citas no me funcionó, pero ^ funcionó como un campeón.
davenpcj

25
^es el carácter de escape solo en cadenas sin comillas ; en cadenas entre comillas dobles, se trata como un literal. A diferencia de los shells de Unix (tipo POSIX), cmd.exeNO ofrece un tratamiento de shell estandarizado de comillas dobles dentro de una cadena de comillas dobles, y la interpretación se deja al programa que se invoca (continúa en el siguiente comentario).
mklement0

9
(continuación del comentario anterior) En la práctica, la mayoría de ejecutables / intérpretes de scripts aplican la convención de C de esperar "caracteres. para escapar como \"dentro de una cadena entre comillas dobles (se aplica al menos a: C / C ++, Python, Perl, Ruby). Por el contrario, ""solo se reconoce en una minoría de casos: en los parámetros pasados ​​a archivos por lotes, "" se reconoce como un incrustado doble cita, pero está retenido como es en el correspondiente %<n>parámetro, incluso después de la eliminación de los que encierran entre comillas dobles con %~<n>. Python amablemente también reconoce "", como una alternativa a \".
mklement0

89

La propia respuesta de eplawless resuelve de manera simple y efectiva su problema específico: reemplaza todas las "instancias en la lista completa de argumentos con \", que es como Bash requiere que las comillas dobles dentro de una cadena de comillas dobles sean representadas.

Para responder en general a la pregunta de cómo escapar de las comillas dobles dentro de una cadena entre comillas dobles utilizandocmd.exe , el intérprete de línea de comandos de Windows (ya sea en la línea de comandos, a menudo todavía llamado erróneamente "indicador de DOS", o en un archivo por lotes): Consulte la parte inferior para ver PowerShell .

tl; dr :

  • Usted debe utilizar"" cuando se pasa una cadena a un (tro) archivo por lotes y se puede utilizar ""con las aplicaciones creadas con Microsoft C 's / C ++ / compiladores NET. (Que también acepta \"), que en Windows incluye Python y Node.js :

    • Ejemplo: foo.bat "We had 3"" of rain."

    • Lo siguiente se aplica solo a los archivos por lotes:

      • ""es la única forma de hacer que el comando interpreter ( cmd.exe) trate toda la cadena entre comillas dobles como un solo argumento.

      • Lamentablemente, sin embargo, no sólo se conservan las comillas dobles adjuntas (como de costumbre), sino también las dobles con escape, por lo que obtener la cadena deseada es un proceso de dos pasos; por ejemplo, asumiendo que la cadena entre comillas dobles se pasa como el primer argumento %1,:

      • set "str=%~1"elimina las comillas dobles adjuntas; set "str=%str:""="%"luego convierte las comillas dobles duplicadas en simples.
        Asegúrese de utilizar las comillas dobles adjuntas alrededor de las partes de la asignación para evitar una interpretación no deseada de los valores.

  • \"es requerido - como la única opción - por muchos otros programas , (por ejemplo, Ruby, Perl, e incluso el propio Windows PowerShell de Microsoft (!)), pero SU USO NO ES SEGURO :

    • \"es lo que requieren muchos ejecutables e intérpretes , incluido Windows PowerShell, cuando se pasan cadenas desde el exterior , o, en el caso de los compiladores de Microsoft, soporte como alternativa a "" , en última instancia, sin embargo, depende del programa de destino analizar la lista de argumentos .
      • Ejemplo: foo.exe "We had 3\" of rain."
    • SIN EMBARGO, EL USO DE \"PUEDE RESULTAR EN LA EJECUCIÓN ARBITRARIA NO DESEADA DE COMANDOS y / o REDIRECCIONES DE ENTRADA / SALIDA :
      • Los siguientes caracteres presentan este riesgo: & | < >
      • Por ejemplo, lo siguiente da como resultado una ejecución no intencionada del vercomando; vea más abajo para una explicación y el siguiente punto de viñeta para una solución alternativa:
        • foo.exe "3\" of snow" "& ver."
    • Para Windows PowerShell , \""y "^""son alternativas sólidas pero limitadas (consulte la sección "Llamar a la CLI de PowerShell ..." a continuación).
  • Si debe usar \", solo hay 3 enfoques seguros , que son, sin embargo, bastante engorrosos : Punta del sombrero a TS por su ayuda.

    • Al usar la expansión de variable retardada (posiblemente selectiva ) en su archivo por lotes, puede almacenar literal \"en una variable y hacer referencia a esa variable dentro de una "..."cadena usando la !var!sintaxis ; consulte la útil respuesta de TS .

      • El enfoque anterior, a pesar de ser engorroso, tiene la ventaja de que se puede aplicar metódicamente y que funciona de manera robusta , con cualquier entrada.
    • Solo con cadenas LITERALES, las que NO involucran VARIABLES, obtiene un enfoque metódico similar: categóricamente, ^escapar de todos los cmd.exe metacaracteres: " & | < > y, si también desea suprimir la expansión de variables %:
      foo.exe ^"3\^" of snow^" ^"^& ver.^"

    • De lo contrario, debe formular su cadena basándose en el reconocimiento de qué partes de la cadena se cmd.execonsideran sin comillas debido a una mala interpretación\" como delimitadores de cierre:

      • en porciones literales que contienen metacaracteres de shell: ^-escape de ellos; usando el ejemplo anterior, es &que se debe ^escapar:
        foo.exe "3\" of snow" "^& ver."

      • en porciones con %...%referencias de variable de estilo : asegúrese de que las cmd.execonsidera parte de una "..."cadena y que los valores de las variables no tienen comillas incrustadas y no balanceadas, lo que ni siquiera siempre es posible .

Para obtener información general, siga leyendo.


Antecedentes

Nota: Esto se basa en mis propios experimentos. Avísame si me equivoco.

Los shells similares a POSIX, como Bash en sistemas similares a Unix, tokenizan la lista de argumentos (cadena) antes de pasar los argumentos individualmente al programa de destino: entre otras expansiones, dividen la lista de argumentos en palabras individuales (división de palabras) y eliminan los caracteres entre comillas del palabras resultantes (eliminación de comillas). El programa de destino recibe una serie de argumentos individuales , sin comillas sintácticas .

Por el contrario, el intérprete de comandos de Windows aparentemente no tokeniza la lista de argumentos y simplemente pasa la cadena única que comprende todos los argumentos, incluidos los caracteres entre comillas. - al programa de destino.
Sin embargo, se realiza un procesamiento previo antes de que la cadena única se pase al programa de destino: ^caracteres de escape. fuera de las cadenas entre comillas dobles se eliminan (escapan al siguiente carácter), y las referencias de variables (por ejemplo, %USERNAME%) se interpolan primero.

Por lo tanto, a diferencia de Unix, es responsabilidad del programa de destino analizar para analizar la cadena de argumentos y dividirla en argumentos individuales sin las comillas. Por lo tanto, diferentes programas pueden requerir hipotéticamente diferentes métodos de escape y no existe un mecanismo de escape único que esté garantizado para funcionar con todos los programas : https://stackoverflow.com/a/4094897/45375 contiene una excelente información sobre la anarquía que es la línea de comandos de Windows. análisis.

En la práctica, \"es muy común, pero NO SEGURO , como se mencionó anteriormente:

Dado que en cmd.exesí mismo no se reconoce \"como una comilla doble de escape , puede malinterpretar los tokens posteriores en la línea de comando como sin comillas y potencialmente interpretarlos como comandos y / o redirecciones de entrada / salida .
En pocas palabras: las superficies de problema, si cualquiera de los siguientes caracteres siguen una abertura o desequilibrada \" :& | < > ; por ejemplo:

foo.exe "3\" of snow" "& ver."

cmd.exeve los siguientes tokens, que resultan de una mala interpretación \"como una comilla doble regular:

  • "3\"
  • of
  • snow" "
  • descanso: & ver.

Como cmd.exepiensa que no& ver. está entre comillas , lo interpreta como &(el operador de secuencia de comandos), seguido del nombre de un comando a ejecutar ( ver.- .se ignora; verinforma cmd.exela información de la versión).
El efecto general es:

  • Primero, foo.exese invoca solo con los primeros 3 tokens.
  • Luego, verse ejecuta el comando .

Incluso en los casos en que el comando accidental no daña, su comando general no funcionará como fue diseñado, dado que no se le pasan todos los argumentos.

Muchos compiladores / intérpretes SÓLO reconocen\" , por ejemplo, el compilador GNU C / C ++, Python, Perl, Ruby, incluso el propio Windows PowerShell de Microsoft cuando se invoca desde cmd.exe, y, excepto (con limitaciones) para Windows PowerShell \"", para ellos no existe una solución simple a este problema.
Esencialmente, tendría que saber de antemano qué partes de su línea de comando se malinterpretan como sin comillas y, de forma selectiva, ^escapar de todas las instancias de & | < >en esas partes.

Por el contrario, el uso de ""es SEGURO , pero lamentablemente solo es compatible con archivos ejecutables y por lotes basados ​​en el compilador de Microsoft (en el caso de los archivos por lotes, con las peculiaridades mencionadas anteriormente), lo que excluye a PowerShell. ; consulte la siguiente sección.


Llamar a la CLI de PowerShell desde cmd.exe o shells similares a POSIX:

Nota: Consulte la sección inferior para ver cómo se manejan las cotizaciones dentro de PowerShell.

Cuando se invoca desde el exterior , por ejemplo, desde cmd.exe, ya sea desde la línea de comando o desde un archivo por lotes:

  • PowerShell [Core] v6 + ahora reconoce correctamente"" (además de\"), que es seguro de usar y preserva los espacios en blanco .

    • pwsh -c " ""a & c"".length " no se rompe y cede correctamente 6
  • Windows PowerShell (la edición heredada cuya última versión es 5.1) reconoce solo \" y, en Windows también """y el más robusto \""/"^"" (aunque internamente PowerShell usa`como carácter de escape en cadenas entre comillas dobles y también acepta""; consulte la sección inferior):

Llamar a Windows PowerShell desdecmd.exe / un archivo por lotes:

  • "" se rompe , porque es fundamentalmente no compatible:

    • powershell -c " ""ab c"".length " -> error "Falta el terminador en la cadena"
  • \"y """ funcionan en principio , pero no son seguros :

    • powershell -c " \"ab c\".length "funciona según lo previsto: produce 5(tenga en cuenta los 2 espacios)
    • Pero no es seguro, porque los cmd.exemetacaracteres rompen el comando, a menos que se escape: se
      powershell -c " \"a& c\".length " rompe , debido al &, que tendría que escaparse como^&
  • \""es seguro , pero normaliza el espacio en blanco interior , lo que puede no ser deseado:

    • powershell -c " \""a& c\"".length "salidas 4(!), porque los 2 espacios están normalizados a 1.
  • "^""es la mejor opción para Windows PowerShell específicamente , donde es seguro y conserva los espacios en blanco, pero con PowerShell Core (en Windows) es lo mismo que\"" , es decir, normalización de espacios en blanco . El crédito es para Venryx por descubrir este enfoque.

    • powershell -c " "^""a& c"^"".length " funciona : no se rompe - a pesar &- y produce 5, es decir, espacios en blanco correctamente conservados.

    • PowerShell Core : pwsh -c " "^""a& c"^"".length " funciona , pero genera 4, es decir, normaliza los espacios en blanco , como lo \""hace.

En plataformas similares a Unix (Linux, macOS), al llamar a la CLI de PowerShell [Core]pwsh , desde un shell similar a POSIX como bash:

Usted debe utilizar\" , que, sin embargo, es seguro y los espacios en blanco de preservación :

$ pwsh -c " \"a&  c|\".length" # OK: 5

Información relacionada

  • ^solo se puede usar como carácter de escape en cadenas sin comillas ; dentro de cadenas entre comillas dobles, ^no es especial y se trata como un literal.

    • ADVERTENCIA : El uso de los ^parámetros in pasados ​​a la calldeclaración está roto (esto se aplica a ambos usos de call: invocar otro archivo por lotes o binario y llamar a una subrutina en el mismo archivo por lotes):
      • ^las instancias en valores entre comillas dobles se duplican inexplicablemente , alterando el valor que se pasa: por ejemplo, si la variable %v%contiene un valor literal a^b, call :foo "%v%"asigna "a^^b"(!) a %1(el primer parámetro) en la subrutina :foo.
      • El uso sin comillas de ^con callse interrumpe por completo, ya que ^ya no se puede usar para escapar de caracteres especiales : por ejemplo,call foo.cmd a^&bse rompe silenciosamente (en lugar de pasar literala&btambiénfoo.cmd, como sería el caso sincall),foo.cmdnunca se invoca (!), Al menos en Windows 7.
  • %Desafortunadamente, escapar de un literal es un caso especial que requiere una sintaxis distinta dependiendo de si se especifica una cadena en la línea de comando o dentro de un archivo por lotes ; ver https://stackoverflow.com/a/31420292/45375

    • En resumen: dentro de un archivo por lotes, use %%. En la línea de comando, %no se puede escapar, pero si coloca un ^al principio, al final o dentro del nombre de una variable en una cadena sin comillas (por ejemplo, echo %^foo%), puede evitar la expansión de la variable (interpolación); %las instancias en la línea de comando que no son parte de una referencia de variable se tratan como literales (por ejemplo, 100%).
  • Generalmente, para trabajar de forma segura con valores de variables que pueden contener espacios y caracteres especiales :

    • Asignación : Incluya tanto el nombre de la variable como el valor en un solo par de comillas dobles ; por ejemplo, set "v=a & b"asigna un valor literal a & ba la variable %v%(por el contrario, set v="a & b"las comillas dobles forman parte del valor). Escapa de las %instancias literales como %%(funciona solo en archivos por lotes; consulte más arriba).
    • Referencia : referencias de variables entre comillas dobles para asegurarse de que su valor no se interpola; por ejemplo, echo "%v%"no somete el valor de %v%a la interpolación y las impresiones "a & b"(pero tenga en cuenta que las comillas dobles también se imprimen invariablemente). Por el contrario, echo %v%pasa literal aa echo, interpreta &como el operador de secuencia de comandos y, por lo tanto, intenta ejecutar un comando llamado b.
      También tenga en cuenta la advertencia anterior sobre el uso de ^la calldeclaración.
    • Los programas externos normalmente se encargan de eliminar las comillas dobles adjuntas alrededor de los parámetros, pero, como se señaló, en los archivos por lotes debe hacerlo usted mismo (por ejemplo, %~1para eliminar las comillas dobles adjuntas del primer parámetro) y, lamentablemente, no hay manera que conozco echopara imprimir un valor variable fielmente sin las comillas dobles adjuntas .
      • Neil ofrece una forsolución alternativa que funciona siempre que el valor no tenga comillas dobles incrustadas ; p.ej:
        set "var=^&')|;,%!" for /f "delims=" %%v in ("%var%") do echo %%~v
  • cmd.exeno no reconocer individuales -quotes como delimitadores de cadenas - que son tratados como literales y en general no pueden ser usados para cuerdas delimitan con espacios en blanco incrustados; Además, se deduce que los tokens que lindan con las comillas simples y los tokens intermedios se tratan como no citados por cmd.exey se interpretan en consecuencia.

    • Sin embargo, dado que los programas de destino en última instancia realizan su propio análisis de argumentos, algunos programas como Ruby reconocen cadenas entre comillas simples incluso en Windows; por el contrario, los ejecutables C / C ++, Perl y Python no los reconocen.
      Sin embargo, incluso si es compatible con el programa de destino, no es aconsejable utilizar cadenas entre comillas simples, dado que su contenido no está protegido de interpretaciones potencialmente no deseadas por cmd.exe.

Citando desde dentro de PowerShell:

Windows PowerShell es un shell mucho más avanzado que cmd.exe, y ha sido parte de Windows durante muchos años (y PowerShell Core también trajo la experiencia de PowerShell a macOS y Linux).

PowerShell funciona de forma coherente internamente con respecto a las citas:

  • dentro de cadenas de comillas dobles, use `"o ""para escapar de las comillas dobles
  • dentro de cadenas de comillas simples, utilícelo ''para escapar de las comillas simples

Esto funciona en la línea de comandos de PowerShell y al pasar parámetros a scripts o funciones de PowerShell desde dentro de PowerShell.

(Como se mencionó anteriormente, pasar una comilla doble de escape a PowerShell desde el exterior requiere \"o, de manera más sólida, \""nada más funciona).

Lamentablemente, al invocar programas externos desde PowerShell, se enfrenta a la necesidad de adaptarse a las propias reglas de cotización de PowerShell y escapar al programa de destino :

Este comportamiento problemático también se discute y se resume en esta respuesta.

Doble -quotes dentro de dobles cadenas -quoted :

Considere una cadena "3`" of rain", que PowerShell traduce internamente a literal 3" of rain.

Si desea pasar esta cadena a un programa externo, debe aplicar el escape del programa de destino además del de PowerShell ; digamos que desea pasar la cadena a un programa en C, que espera que las comillas dobles incrustadas se escapen como \":

foo.exe "3\`" of rain"

Tenga en cuenta que ambos `" , para hacer feliz a PowerShell, y el \, para hacer feliz al programa de destino, deben estar presentes.

La misma lógica se aplica a la invocación de un archivo por lotes, donde se ""debe utilizar:

foo.bat "3`"`" of rain"

Por el contrario, incrustar comillas simples en una cadena de comillas dobles no requiere ningún tipo de escape.

Individuales -quotes dentro individuales cadenas -quoted no no requerir extra de escape; considere'2'' of snow', que es la representación de PowerShell de2' of snow.

foo.exe '2'' of snow'
foo.bat '2'' of snow'

PowerShell traduce cadenas entre comillas simples en comillas dobles antes de pasarlas al programa de destino.

Sin embargo, las comillas dobles dentro de cadenas entre comillas simples , que no necesitan escapar para PowerShell , aún deben escaparse para el programa de destino :

foo.exe '3\" of rain'
foo.bat '3"" of rain'

PowerShell v3 introdujo la --%opción mágica , llamada símbolo de detener el análisis , que alivia parte del dolor, al pasar cualquier cosa después de que no se interprete al programa de destino, excepto cmd.exelas referencias de variables de entorno de estilo (por ejemplo, %USERNAME%), que se expanden; p.ej:

foo.exe --% "3\" of rain" -u %USERNAME%

Tenga en cuenta que es suficiente escapar del incrustado "como solo \"para el programa de destino (y no también para PowerShell como \`").

Sin embargo, este enfoque:

  • no permite caracteres de escape % para evitar expansiones de variables de entorno.
  • excluye el uso directo de variables y expresiones de PowerShell; en su lugar, la línea de comando debe construirse en una variable de cadena en un primer paso y luego invocarse con Invoke-Expressionen un segundo.

Por lo tanto, a pesar de sus muchos avances, PowerShell no ha facilitado mucho el escape al llamar a programas externos. Sin embargo, ha introducido soporte para cadenas de comillas simples.

Me pregunto si es fundamentalmente posible en el mundo de Windows cambiar alguna vez al modelo Unix de dejar que el shell haga toda la tokenización y la eliminación de cotizaciones de manera predecible , por adelantado , independientemente del programa de destino , y luego invocar el programa de destino pasando los tokens resultantes .


¡Buena descripción! Pero ... Literal use of ^ in double-quoted strings can, be problematic when applying ~ ...no realmente. La tilde solo elimina las comillas externas cuando están presentes. La pérdida de intercalaciones es un problema de manejo en sí. Normalmente, un set "param=%~1"resuelve esto.
jeb

Gracias, @jeb, el problema no es específico para su uso ~. He actualizado mi respuesta para reflejar mi nueva comprensión. Por favor, comente, si detecta un problema. ¿Tiene una explicación para la duplicación ^que ocurre automáticamente cuando pasa parámetros a una calldeclaración?
mklement0

3
Solo puedo suponer que alguien en MS pensó que era brillante. Que los signos de intercalación duplicados se eliminarán automáticamente en la segunda fase de análisis. Pero esto fue un gran error, ya que no funciona entre comillas y evita efectivamente el escape de caracteres especiales. Como call echo cat^^&dogsi no se pudiera resolver con ninguna cantidad de intercalaciones solo
jeb

Gracias, @jeb, ni siquiera había considerado el uso no citado de ^with call, que, como señala, está muy roto. Parece que en call echo cat^&dog(single ^que escapa correctamente al &) el comando de destino ( echo) ni siquiera se invoca (!) - el comando completo falla silenciosamente. Actualicé la respuesta en consecuencia.
mklement0

Buena respuesta. Sin embargo, no recomendaría ""como escapado, "pero siempre \"(consulte mi respuesta para conocer una forma menos peligrosa de usarlo desde cmd). No sé ninguna documentación oficial que define ""como un escaparon cita, pero por lo menos 2 que mencionan \": .NET y VS . Aunque está mal documentado, la API de Win32 también sigue estas reglas.
TS

23

Google finalmente encontró la respuesta. La sintaxis para el reemplazo de cadenas por lotes es la siguiente:

set v_myvar=replace me
set v_myvar=%v_myvar:ace=icate%

Lo que produce "replicame". Mi secuencia de comandos ahora se ve así:

@echo off
set v_params=%*
set v_params=%v_params:"=\"%
call bash -c "g++-linux-4.1 %v_params%"

Lo que reemplaza todas las instancias de "with \", correctamente escapado para bash.


9

Como complemento a la excelente respuesta de mklement0 :

Casi todos los ejecutables aceptan \"como escapado ". Sin embargo, el uso seguro en cmd casi solo es posible con DELAYEDEXPANSION.
Para enviar explícitamente un literal "a algún proceso, asigne \"una variable de entorno y luego use esa variable, siempre que necesite pasar una cita. Ejemplo:

SETLOCAL ENABLEDELAYEDEXPANSION
set q=\"
child "malicious argument!q!&whoami"

Note SETLOCAL ENABLEDELAYEDEXPANSIONparece funcionar solo en archivos por lotes. Para obtener EXPANSIÓN RETARDADA en una sesión interactiva, comience cmd /V:ON.

Si su archivo por lotes no funciona con DELAYEDEXPANSION, puede habilitarlo temporalmente:

::region without DELAYEDEXPANSION

SETLOCAL ENABLEDELAYEDEXPANSION
::region with DELAYEDEXPANSION
set q=\"
echoarg.exe "ab !q! & echo danger"
ENDLOCAL

::region without DELAYEDEXPANSION

Si desea pasar contenido dinámico de una variable que contiene comillas que se escapan, ya ""que puede reemplazar ""con una \"expansión:

SETLOCAL ENABLEDELAYEDEXPANSION
foo.exe "danger & bar=region with !dynamic_content:""=\"! & danger"
ENDLOCAL

¡Este reemplazo no es seguro con la %...%expansión de estilo!

En caso de OP bash -c "g++-linux-4.1 !v_params:"=\"!" es la versión segura.


Si por alguna razón, incluso habilitar temporalmente la EXPANSIÓN RETARDADA no es una opción, siga leyendo:

Usar \"desde dentro de cmd es un poco más seguro si siempre se necesita escapar de los caracteres especiales, en lugar de solo algunas veces. (Es menos probable que olvide un símbolo de intercalación, si es consistente ...)

Para lograr esto, una cita precede con un signo de intercalación ( ^"), las comillas que deben llegar al proceso hijo como literales deben escaparse adicionalmente con una reacción ( \^"). TODOS los metacaracteres de shell también deben tener un escape ^, por ejemplo &=> ^&; |=> ^|; >=> ^>; etc.

Ejemplo:

child ^"malicious argument\^"^&whoami^"

Fuente: Todo el mundo cita los argumentos de la línea de comandos de forma incorrecta , consulte "Un método mejor para citar".


Para pasar contenido dinámico, es necesario asegurarse de lo siguiente:
La parte del comando que contiene la variable debe ser considerada "entre comillas" por cmd.exe(Esto es imposible si la variable puede contener comillas, no escriba%var:""=\"% ). Para lograr esto, el último "antes de la variable y el primero "después de la variable no se ^escapan. cmd-metacaracteres entre esos dos "no deben escaparse. Ejemplo:

foo.exe ^"danger ^& bar=\"region with %dynamic_content% & danger\"^"

Esto no es seguro, si %dynamic_content%puede contener citas que no coinciden.


Entendido, gracias. Sí, ^escapar categóricamente de todos los metacaracteres funciona de manera sólida y se puede aplicar de manera más metódica (sin embargo, obviamente es un dolor real en la parte del cuerpo que elijas). He actualizado mi respuesta en consecuencia (y le he dado crédito).
mklement0

@ mklement0 ¡Gracias! Sí, realmente es una molestia. Es molesto y todavía es demasiado fácil olvidar un metacarácter (por lo tanto, uso principalmente la !q!forma). Nota: Su respuesta es un poco incoherente después de su última edición: Cerca de la parte superior que dice: "No , no use ^"". Más tarde, lo utilizará ^"como parte de la solución alternativa. ¿Quizás podrías explicar ambas cosas? (1) Escapando de todos los metacaracteres (más metódicamente) / (2) Escapando selectivamente de los metacaracteres en regiones "sin comillas" (a veces es necesario para pasar contenido dinámico, p foo.exe ^"danger ^& bar=\"%dynamic_content%\"^". Ej ., De esta manera la variable se cita para cmd)
TS

Buen punto, gracias - respuesta actualizada. También he dejado más claro que el compilador de MS acepta tanto \"y "". Me he vinculado a su respuesta para el enfoque basado en variables más complicado. Déjame saber si tiene sentido ahora.
mklement0

1
@ mklement0 Tu respuesta siempre tuvo sentido :-) Solo quería dar algunas ideas para posibles mejoras. También agregué el ejemplo sobre %dynamic_content%en mi respuesta. ¿Crees que es lo suficientemente detallado o tengo que explicar más?
TS

3
Genial, gracias por hacérmelo saber. Es una buena idea localizar el setlocal delayedexpansion, pero debe terminar el bloque con endlocal(sin argumento). Honestamente, mi cabeza comenzó a dar vueltas al mirar tu esencia. Realmente estamos lidiando con casos extremos aquí, y creo que los futuros lectores encontrarán todo lo que necesitan entre nuestras dos respuestas.
mklement0

0

Si la cadena ya está entre comillas, utilice otra comilla para anular su acción.

echo "Insert tablename(col1) Values('""val1""')" 

-3

Por ejemplo, para la herramienta Unreal Engine Automation que se ejecuta desde un archivo por lotes, esto funcionó para mí

Por ejemplo: -cmdline = "-Messaging" -device = device -addcmdline = "- SessionId = session -SessionOwner = 'owner' -SessionName = 'Build' -dataProviderMode = local -LogCmds = 'LogCommodity OFF' -execcmds = 'lista de automatización ; ejecuta pruebas + separadas + por + T1 + T2; salir '"-run

Espero que esto ayude a alguien, funcionó para mí.


Trate de resumir el concepto que aprendió que está tratando de compartir en un ejemplo claro, en lugar de copiar y pegar de su trabajo.
run_the_race
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.