C# Análisis en Línea de Comandos de Rutas Entrecomilladas y Evitar Caracteres de Escape


¿Cómo es posible analizar los argumentos de la línea de comandos que deben interpretarse como rutas? args [] contiene cadenas que se unen automáticamente si se citan, por ejemplo:

Ejemplo.exe uno, dos, tres "cuatro"

args[0] = one
args[1] = two
args[2] = three four

Sin embargo, args [] no analizará sus propiedades "C:\Example\" como argumento. Más bien, proporcionará el argumento como "C:\Example "" (con la cita extra incluida.) Esto se debe a que la barra invertida en la ruta se trata como un carácter de escape y, por lo tanto, el final la cita que el usuario proporciona en la línea de comandos se convierte en parte del argumento.

.por ejemplo:

Ejemplo.exe uno "C:\InputFolder ""C:\OutuptFolder\"

args[0] = one
args[1] = C:\InputFolder"
args[2] = C:\OutputFolder"

Un kludge fácil podría ser:

_path = args[i].Replace("\"", @"\");

Sin embargo, estoy seguro de que hay una mejor práctica para esto. ¿Cómo se podría analizar correctamente una línea de comandos que incluye rutas, evitando que la matriz args[] se rellene incorrectamente con picaduras que se han analizado para caracteres de escape?

NOTA: no me gustaría incluir toda una biblioteca de análisis de línea de comandos en mi proyecto! Solo necesito manejar rutas citadas y deseo hacerlo de manera" manual". Por favor, no recomiende NConsoler, Mono, o cualquier otra gran biblioteca de análisis de línea de comandos "fregadero de cocina".

TAMBIÉN NOTA: Por lo que puedo decir, esta no es una pregunta duplicada. Mientras que otras preguntas se centran en el análisis genérico de la línea de comandos, esta pregunta es específica para el problema que las rutas introducen cuando partes de ellas se interpretan como escape secuencia.

Author: James, 2009-05-23

3 answers

No es una respuesta, pero aquí hay algunos antecedentes y explicación de Jeffrey Tan, Microsoft Online Community Support (12/7/2006):

Nota: esto no es una derrota de código pero por diseño, ya que la barra invertida son normalmente se utiliza para escapar de ciertas carácter especial. Además, esto el algoritmo es el mismo que el comando Win32 argumentos de línea función de análisis CommandLineToArgvW. Ver las observaciones sección siguiente: http://msdn2.microsoft.com/en-us/library/bb776391.aspx

También hace referencia al entorno del método FX .GetCommandLineArgs para mayor explicación del comportamiento de manejo de barras.

Personalmente creo que esto es un lastre, y me sorprende que no me haya mordido antes. ¿O tal vez lo tengo y no lo sé? Sin embargo, el reemplazo ciego de citas con barras no me parece una solución. Voy a votar la pregunta, porque fue una revelación.

 8
Author: ewbi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-22 21:59:41

Me gusta tu idea:

_path = args[i].Replace("\"", @"\");

Está limpio, y no tendrá ningún efecto a menos que el problema exista.

 1
Author: Robert Harvey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-22 21:47:48

Tuve la misma frustración. Mi solución fue usar expresiones regulares. Mi entrada esperada es una lista de rutas, algunas de las cuales pueden ser citadas. El kludge anterior no funciona a menos que se citen todos los últimos argumentos.

// Capture quoted string or non-quoted strings followed by whitespace
string exp = @"^(?:""([^""]*)""\s*|([^""\s]+)\s*)+";
Match m = Regex.Match(Environment.CommandLine, exp);

// Expect three Groups
// group[0] = entire match
// group[1] = matches from left capturing group
// group[2] = matches from right capturing group
if (m.Groups.Count < 3)
    throw new ArgumentException("A minimum of 2 arguments are required for this program");

// Sort the captures by their original postion
var captures = m.Groups[1].Captures.Cast<Capture>().Concat(
               m.Groups[2].Captures.Cast<Capture>()).
               OrderBy(x => x.Index).
               ToArray();

// captures[0] is the executable file
if (captures.Length < 3)
    throw new ArgumentException("A minimum of 2 arguments are required for this program");

¿Puede alguien ver una expresión regular más eficiente?

 1
Author: Terrence,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-07 02:40:57