2011-10-29 17 views
7

he encontrado un problema muy extraño con el intérprete de comandos de Windows. Ocurre tanto en XP y Windows 7. Mi descripción siguiente se aplica a un script Perl, pero este problema se aplica a la ejecución de cualquier tipo de programa de la línea de comandos que toma parámetros línea de comandos.escapado Doble Cita efecto secundario de comandos de Windows

Para una prueba de que estoy usando un script Perl check-params.pl que simplemente se da salida a lo que veía como parámetros -

use strict; 
use warnings; 
while (my $param = shift @ARGV) { 
    print "Param: [$param]\n"; 
} 

Por lo tanto si me quedo -

perl check-params.pl "a b|<>" c^|^<^>cc 

A continuación, la salida es

[Param: a b|<>] 
[Param: c|<>cc] 

como se esperaba. Los caracteres especiales | <> funcionan bien dentro de las comillas dobles, pero cuando las cotizaciones fuera te escape ninguno con ^.

Sin embargo, cuando se añade una doble cita con el parámetro citado por ejemplo, en

perl check-params.pl "a\" b|<>" 

Entonces me sale el error -

> was unexpected at this time. 

Pero si el doble cita viene después el carbón especiales | < o>, entonces funciona bien.

Puede solucionar este escapando el especial | <> char con^dentro del parámetro citado. por ejemplo

perl check-params.pl "a\" b^|" 

Sin embargo no sólo afecta a la cotización doble escapado a los caracteres especiales | <> en el parámetro actual sino que afecta a estos caracteres especiales dentro de los parámetros siguientes.

por ejemplo si hago esto -

perl check-params.pl "aa \"bb" ccc | perl check-pipe.pl 

(donde check-pipe.pl emite simplemente lo que la tubería recibido -

use strict; 
use warnings; 
while (<STDIN>) { 
    print "PIPE RECEIVED ---> $_"; 
} 

)

entonces la salida es -

Param: [aa "bb] 
Param: [ccc] 
Param: [|] 
Param: [perl] 
Param: [check-pipe.pl] 

es decir, trata el tubo | como un personaje literal, y no se producen tuberías.

¿Alguien ha tenido alguna experiencia con este problema y conoce alguna solución?

He escrito algunas secuencias de comandos Perl para procesar archivos de registro web, y una utiliza expresiones regulares, que paso dentro de un parámetro citado en la línea de comandos. La expresión regular puede contener caracteres como | <>, y puede tener una comilla doble también, que ingreso como \ ". Por lo tanto, el problema anterior está apareciendo.

Cualquier ayuda muy apreciada, gracias.


Gracias por responder, pero al intentar esto en XP SP3, el script Perl está viendo dos parámetros de línea de comandos.

Este problema no está relacionado con Perl, por ejemplo

echo "a \"b|c" 

produce error -

'c"' is not recognized as an internal or external command, 
operable program or batch file. 

pero

echo "a b|\"c" 

obras, ya que el \" viene después de la carbonización especiales |

It debe ser un error en el intérprete de comandos. Me interesaría saber más sobre esto, y encontrar una solución si es posible. Este problema arruina la ejecución de algunas secuencias de comandos útiles. Es un problema bastante evidente para un intérprete de comandos. Intenté con Windows 7 también, y el mismo problema ocurre allí con la prueba de eco anterior.


Información adicional:

He actualizado los scripts check-params.pl y check-pipe.pl para dar una información más útil: -

check-params.pl: -

use strict; 
use warnings; 
while (my $param = shift @ARGV) { 
    print "COMMAND LINE RECEIVED: [$param]\n"; 
} 

check-pipe.pl: -

use strict; 
use warnings; 
while (<STDIN>) { 
    print "PIPE RECEIVED: $_"; 
} 

while (my $param = shift @ARGV) { 
    print "COMMAND LINE RECEIVED: [$param]\n"; 
} 

Por ejemplo en funcionamiento: -

perl pl/utils/check-params.pl l1 l1-b l1-c | perl pl/utils/check-pipe.pl l2 l2-b | perl pl/utils/check-pipe.pl l3 l3-b | perl pl/utils/check-pipe.pl united arsenal rangers raith 

produce una salida: -

PIPE RECEIVED: PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l1] 
PIPE RECEIVED: PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l1-b] 
PIPE RECEIVED: PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l1-c] 
PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l2] 
PIPE RECEIVED: PIPE RECEIVED: COMMAND LINE RECEIVED: [l2-b] 
PIPE RECEIVED: COMMAND LINE RECEIVED: [l3] 
PIPE RECEIVED: COMMAND LINE RECEIVED: [l3-b] 
COMMAND LINE RECEIVED: [united] 
COMMAND LINE RECEIVED: [arsenal] 
COMMAND LINE RECEIVED: [rangers] 
COMMAND LINE RECEIVED: [raith] 

confirmando así que esta línea de comandos funcionará como se espera. Los scripts funcionarán con cualquier cantidad de tuberías en la línea de comando.


Información adicional:

encuentro que puedo conseguir que esto funcione utilizando numerosas soluciones - por ejemplo, el^"Harry mencionado es un ejemplo veces se puede recraft la expresión regular para evitar el uso de la.". Cuando hay dos \ "secuencias antes del carácter especial | <>, entonces el problema no ocurre. Antes de ejecutar cualquier comando, ejecuto check-params.pl y check-pipe.pl para verificar cómo los scripts de Perl verán los parámetros de la línea de comando. , por ejemplo, la edición anterior de mi OP describe estos scripts, que he modificado desde mi OP.

+0

Aunque creo que he encontrado una solución para usted (consulte la última edición de mi respuesta) si está ingresando las expresiones regulares de manera interactiva, es posible que le resulte más conveniente que sus scripts las soliciten en lugar de ponerlas en el línea de comando. De esa forma no tendrás que escapar de todos los personajes especiales. –

+0

Muchas gracias por la información. Me había ganado la impresión de mis pruebas en mi OP que "era una secuencia de escape. No es factible para mí ingresar a los parámetros de línea de comando a través de un aviso ya que tengo muchos comandos y son bastante complejos. Copio y pego de un archivo de texto y, a veces, copio varios y los ejecuto todos a la vez. (Con el modo de edición rápida puede hacer clic derecho para pegar en la ventana de comandos). –

Respuesta

2

Se considera que la comilla doble en \ "coincide con la comilla doble inicial, finalizando el parámetro citado. Para incluir una doble cita en un parámetro citado utilizar dos comillas dobles:

perl check-params.pl "a"" b|<>" 

deberían producir el resultado que esperas, dependiendo de cómo perl.exe analiza los parámetros de línea de comandos (He probado el uso de scripts de comandos como No tengo Perl instalado).Tendrá que cambiar la secuencia de comandos para que "" en lugar de \" se trata como una doble cita

adicional:. Esta línea de comandos

echo "a \"b|c" 

produce un mensaje de error al iniciar c" is not recognized. esto no es un error.

una barra invertida no es un carácter de escape, por lo que la línea de comandos contiene una cadena entre comillas ("a \") seguido de una tubería (|), que hace que el resto (c") un comando adicional, que la salida del comando echo se canaliza.

Si en lugar de decir

echo "a ""b|c" 

entonces no es sólo una cadena entre comillas ("a ""b|c") y funcionará como se espera.

Por desgracia, ahora puedo confirmar que el análisis de línea de comandos de ActivePerl causa

perl check-params.pl "a"" b|" 

se divida en dos parámetros. Es posible que necesite recuperar toda la línea de comando (si hay una forma de hacerlo en Perl) y analizarlo usted mismo.

adicional:

perl check-params.pl ^"a\^" b^|c^" 

produce el resultado deseado. Esto funciona escapando de todos los caracteres especiales, incluidas las comillas.

+0

El^"es bastante útil, y he agregado esto a mis numerosas soluciones. Parece que hay 2 problemas aquí, uno es cómo funciona el intérprete de comandos de Windows, y el otro es cómo Perl analiza una línea de comandos. –

Cuestiones relacionadas