2009-05-22 18 views
21

¿Cómo es posible analizar argumentos de línea de comandos que se deben interpretar como rutas? args [] contiene cadenas que están unidas de forma automática si se citan, por ejemplo:Análisis de línea de comandos C# de rutas citadas y evitar caracteres de escape

ejemplo.exe uno dos "tres, cuatro"

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

Sin embargo, args [] no la propiedad de análisis "C: \ Ejemplo \ "como un argumento. Más bien, proporcionará el argumento como "C: \ Ejemplo" "(con la comilla extra incluida). Esto se debe a la barra diagonal inversa en la ruta que se trata como un carácter de escape y, por lo tanto, a la cita final que el usuario suministró en el comando -line se convierte en parte del argumento

.eg:.

uno ejemplo.exe "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 puede analizar correctamente una línea de comando que incluye rutas, evitando que la matriz args [] se llene incorrectamente con picaduras que se han analizado para caracteres de escape?

NOTA: ¡No me gustaría incluir una biblioteca de análisis de línea de comandos completa en mi proyecto! Solo necesito manejar rutas citadas y deseo hacerlo de una manera "manual". No recomiende NConsoler, Mono o cualquier otra gran biblioteca de análisis de línea de comandos del "fregadero de la 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 línea de comandos, esta pregunta es específica del problema que las rutas introducen cuando partes de ellas se interpretan como secuencias de escape.

+0

¿Dónde está exactamente viendo este personaje extra? Estoy usando el compilador de fragmentos. Aquí está el principal ... cadena s = args [0]; \t \t Console.WriteLine (s); Y funciona como debería. – shahkalpesh

+0

@shahkalpesh: No sé sobre el compilador de fragmentos, pero intente ejecutarlo desde la línea de comandos y suministre a su programa un argumento que termine en \ "(barra invertida-doble citación). Como dijo ebwi, abrí los ojos. –

+0

Lo entiendo ahora. Perdón por no haber entendido correctamente el argumento de entrada. – shahkalpesh

Respuesta

8
No

una respuesta, pero éstas son algunas de background and explanation Jeffrey Tan, Microsoft Online comunitario de apoyo (12/7/2006):

Nota: esto no es ni una derrota código sino por diseño, ya backslashe son normalmente utilizados para escapar de ciertos caracteres especiales . Además, este algoritmo es el mismo que el comando Win32 argumentos de línea que analiza la función CommandLineToArgvW. Véanse las observaciones sección a continuación: http://msdn2.microsoft.com/en-us/library/bb776391.aspx

también hace referencia al método de FX Environment.GetCommandLineArgs para una explicación más detallada del comportamiento de manejo barra.

Personalmente creo que esto es un lastre, y estoy sorprendido de que no me hayan 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. Votaré la pregunta, porque fue una revelación.

1

me gusta su idea:

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

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

+0

Pero esto no funcionará si tiene: example.exe una "C: \ InputFolder \" "C: \ OutuptFolder \", ya que las dos rutas quedarán concatenadas como arg [1] = C: \ InputFolder "C: \ Outpurfolder" –

1

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 citarse. 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"); 

¿Alguien puede ver una expresión regular más eficiente?

Cuestiones relacionadas