Escapar de comillas y comillas dobles

94

¿Cómo puedo escapar correctamente de las comillas en el -paramvalor en la siguiente línea de comando?

$cmd="\\server\toto.exe -batch=B -param="sort1;parmtxt='Security ID=1234'""
Invoke-Expression $cmd 

Esto, por supuesto, falla. Traté de escapar de las comillas (simples y dobles) usando el carácter de escape `e hice varias combinaciones, pero nada funciona.

eetawil
fuente
Consulte también Invocar-Expresión considerada dañina .
Peter Mortensen
@PeterMortensen, el problema con este artículo es que no parece haber una mejor manera, cuando desea iniciar una aplicación nativa y pasar un parámetro que incluye una comilla doble como argumento
Andrew Savinykh
@ Andrew Savinyj: Una forma es poner en marcha a través de cmd en su lugar: $someCommandStringWithDoubleQuotes | cmd. En realidad, esto funciona desde scripts de PowerShell (por ejemplo, invocando CMake (que requiere las comillas dobles (de lo contrario, fallará silenciosamente))). Una alternativa a CMD es bash.exe ( MinGW ), pero su inicio puede ser muy, muy lento en algunas circunstancias.
Peter Mortensen

Respuestas:

59

Escapar de parámetros como ese suele ser una fuente de frustración y se siente como una pérdida de tiempo. Veo que estás en la v2, así que te sugiero que uses una técnica sobre la que Joel "Jaykul" Bennet escribió en su blog hace un tiempo .

En pocas palabras: simplemente envuelve tu cadena con @ '...' @:

Start-Process \\server\toto.exe @'
-batch=B -param="sort1;parmtxt='Security ID=1234'"
'@

(Tenga en cuenta que asumí qué comillas son necesarias y qué cosas intentaba escapar). Si desea trabajar con la salida, es posible que desee agregar el -NoNewWindowmodificador.

Por cierto: este fue un problema tan importante que, desde la versión 3, puede usar --%para evitar que el analizador de PowerShell haga algo con sus parámetros:

\\server\toto.exe --% -batch=b -param="sort1;paramtxt='Security ID=1234'"

... debería funcionar bien allí (con la misma suposición).

BartekB
fuente
Gracias por tu respuesta. start-process no importa cómo lo intenté siempre me quejé. Así que hice cmd / C $ cmd (donde $ cmd es mi comando completo, incluido el .exe). Estoy usando powershell 2.0. Incluso la cadena here no funcionó si no recuerdo mal.
eetawil
3
Esto parece innecesariamente complicado en comparación con el uso de comillas invertidas (`) para escapar de las comillas dobles.
Saille
6
Esto funciona muy bien siempre que siga las reglas que espera. La primera @ 'debe estar en la "línea 1", su parámetro debe estar en la "línea 2" y el final' @ debe estar en la "línea 3". La terminación '@ no puede tener espacios antes. ¡Hombre, esta sintaxis es delicada!
Ian Newland
¡Funciona genial! Si necesita expandir variables en su cadena, puede usar @"y en su "@lugar.
browly
97

Usar la comilla invertida (`) funciona bien para mí si los coloco en los siguientes lugares:

$cmd="\\server\toto.exe -batch=B -param=`"sort1;parmtxt='Security ID=1234'`""

$cmd devuelve como:

\\server\toto.exe -batch=B -param="sort1;parmtxt='Security ID=1234'"

¿Es eso lo que estabas buscando?

El error que me dio PowerShell se refería a un token inesperado 'sort1', y así fue como determiné dónde colocar las comillas invertidas.

La sintaxis @ '...' @ se denomina "cadena aquí" y devolverá exactamente lo que se ingresó. También puede usarlos para completar variables de la siguiente manera:

$cmd=@'
"\\server\toto.exe -batch=B -param="sort1;parmtxt='Security ID=1234'""
'@

Los símbolos de apertura y cierre deben estar en su propia línea como se muestra arriba.

Owen B
fuente
Perdón por la demora ... la forma en que lo hice funcionar es finalmente llamar a cmd / C "MYCOMMAND" desde powershell. No funcionó usando PowerShell directamente.
eetawil
1
¿Pero no Invoke-Expressionquita las comillas dobles de $cmdcuando se invoca? ¿O cómo lo usaste $cmdsin usar Invoke-Expression?
Peter Mortensen
8

Hoy me encontré en una situación similar mientras intentaba ejecutar un comando a través de un módulo Node.js:

Estaba usando PowerShell y tratando de ejecutar:

command -e 'func($a)'

Pero con los símbolos adicionales, PowerShell estaba destrozando los argumentos. Para solucionarlo, marqué hacia atrás las comillas dobles escapadas:

command -e `"func($a)`"
pranspach
fuente
2
interesante: "['`"][^'`"]['`"]"funciona… ¡pero '[`'"][^`'"][`'"]'no! me estaba volviendo loco
David J