2013-04-19 2 views
4

나는 같이 명령 행 인수 세트를 구문 분석합니다.구문 분석하는 방법 명령 줄 인수

나는 NDesk.Options

var set = new OptionSet { 
    { "p=", "the project file", v => { /* do stuff */ } }, 
    { "s=", "a setting", (m, v) => { /* do stuff */ } }, 
}; 

를 사용하여 시도하고 이것은 대부분의 경우에서 잘 작동하지만, value 파일 경로 (심지어 인용)이 때 \ 오른쪽으로 모든 것을 드롭 파서됩니다. 나는 NDesk.Options.OptionSet에서 상속 한 내 자신의 OptionSet 클래스의 구문 분석 메서드를 재정 의하여 이것을 해킹했습니다. 그러나이 기능을 상자 밖으로 처리 할 수있는 라이브러리가 있는지 궁금합니다.

UPDATE

미안 내가이 어쨌든 실패 예제를 설정 : 생각합니다 \은되지 않은 : 그들은 모두 성공적으로 OptionException Error: Found 3 option values when expecting 2.

+0

예제 명령 줄에 실패 할 수 있습니까? 전체 인수 또는 파일 이름 부분 만 인용 했습니까? – CodesInChaos

답변

5

업데이트 : 설정 값에서 콜론을 처리하도록 업데이트되었습니다.

OK, 그래서 여기에 당신은 Setting=C:\Path 3 개 값 (설정, C, \ 경로로 구문 분석하는 의미, 다중 매개 변수를 모두 :=이 값 구분자로 간주된다는 점이다 NDesk.Options의 암시 적 기본값 중 하나에 실행) 예상되는 2 대신. 이 문제를 해결하기 위해

, 당신은 단순히 대신 "s=""s={=}"를 작성하여 만 유효한 구분자로 =을 고려해야 할 -s 옵션 정의를 수정해야합니다.

원본 대답, 백 슬래시와 관련된 내용입니다.

따옴표로 묶인 경로 및 백 슬래시에 문제가 발생하지 않고 NDesk.Options을 사용했습니다. 여기

내 샘플 프로그램입니다 :

public static void Main(string[] args) 
{ 
    string parsedPath = null; 
    Dictionary<string, string> parsedValues = new Dictionary<string, string>(); 
    var set = new OptionSet() 
    { 
     { "p=", "the project path", v => parsedPath = v }, 
     { "s=", "a setting", (m, v) => { parsedValues.Add(m, v); } }, 
    }; 
    set.Parse(args); 
    Console.WriteLine(parsedPath ?? "<NULL>"); 
    foreach (var keyValuePair in parsedValues) 
    { 
     Console.WriteLine(keyValuePair.Key + "::::" + keyValuePair.Value); 
    } 
} 

당신은 당신의 정의와 내 사이에 차이가 있음을 볼 수 있습니다 : p=이 옵션은 필요한 값을 가지고 있다는 것을 의미 당신의 정의는 p 부울 것을 의미하지만, 플래그 값.

p 설정 또는 s 설정에서 백 슬래시와 관련하여 문제가 발생하지 않았습니다. 버전 0.2.1의 NDesk.Options으로 프로그램을 실행하고 어떤 값이 실패했는지 보여줄 수 있습니까?

-sGreeting=Hello\My World -- // This gives Greeting="Hello\My" 

주 : 그 아무것도 변경하는 경우 여기에

-p=..\Path 
-p..\Path 
-pC:\Hello 
-pHello\World 
-p"Hello\World" 
-s"Greeting=Hello\World" 
-sGreeting="Hello\World" 
-sGreeting=Hello\World 
-sGreeting="Hello\My World" 
-s"Greeting=Hello\My World" 

는 언급 가치가 다른 결과를 생성 할 몇 가지 구문 분석이다 : 여기

모두 성공적으로 구문 분석 내가 달릴 몇 가지 샘플입니다 , NDesk.Options를 프로젝트의 Options.cs 소스 코드 파일로 실행했지만 컴파일 된 DLL로 실행하지 않았습니다.

+0

테스트 사례에 약간의 공백을 추가하면 해를 끼치 지 않을 것입니다. – CodesInChaos

+0

@CodesInChaos : 분명히 그것은 내가 추가했을 것이지만, 그 단계에서 볼 수는 없었습니다. NDesk.Options에 명백한 문제가 있습니다. 원격으로도 그의 설명처럼 보입니다. 역 슬래시의 모든 것이 삭제되므로 문제가 무엇인지 물어볼 수도 있습니다. –

+0

고마움, 월요일에 사무실에 돌아 왔을 때 시도해 볼 것이고 작동한다면 받아 들일 것입니다. 관심 밖의 내용은 문서화 된 기능입니다. 나는 내가 볼 수있는 모든 문서를 읽고 그 것을 보았던 것을 기억하지 못합니까? – briantyler

0

당신은 하나의 문자열에 모든 인수를 joinh 수 있습니다 그리고 당신은 정규 표현식을 사용할 수 있습니다 : 당신이

필요 후 정보를 추출 그룹
var groups = new Regex(yourRegex).Match(message).Groups; 

로하고보다 문자열을 분할
((?<SkeyvaluePair>-s(?<key>[^=]+)\s*=\s*(?<value>[^-]+))|(?<PkeyvaluePair>-p(?<Pvalue>[^-]+)))* 

var pairs = groups["keyvaluepair"].Captures.Cast<Capture>() 
2

다음과 같이 사용하면 모든 분할이 수행됩니다.

public static void Main(string[] args) 
    { 
     List<string> Settings = new list 
     Console.WriteLine("parameter qty = {0}", args.Length); 
     for(int i = 0; i < args.Length; i++) 
     { 
      Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]); 
     } 

각 인수를 기반으로 필요한 조치를 취하는 간단한 if 세트 만 있으면 충분합니다. 인수 배열의 각 인수를 반복하여 원하는대로 문자열 일치 또는 정규 표현식을 사용하여 어떤 arg를 준수하는지 확인할 수 있습니다. 당신이 루프의 일부 코드를 추가 할 수 있습니다 eaxmple를 들어 :

public static void Main(string[] args) 
    { 
     List<string> Settings = new List<string>(); 
     Console.WriteLine("parameter qty = {0}", args.Length); 
     for(int i = 0; i < args.Length; i++) 
     { 
      Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]); 
      if (i>0) 
       { 
        // this gives you a nice iterable list of settings 
        Setting.Add(args[i]); 
       } 
     } 
     foreach(string setting in Settings) 
      { 
       //do the desired action 
      } 
    } 

부록 :이 의지하지만, 나처럼 당신이 C++에서이고 일을해야하는 경우 괜찮 기본적인 기능 (제공 C# 개발자 관점에서 그렇게 나쁘지는 않습니다.), 당신은 variant 명령의 구문 분석을 처리해야합니다 (주석 /p--p or /Project= -Project=에서 언급했듯이 변종은 모두 코드에서 처리해야합니다). 그러나 밖으로 상자 해결책을 위해 나는 추천 할 것입니다 : Ndesk.Options 또는 Mono.Options 둘 다 비슷하게 작동하고, 휴대 성이 중요했던 경우에 Mono.Options 경향이있었습니다.사용 중

당신은

var set = new OptionSet { 
    { "p=|project=", "the project file", v => { /* do stuff */ } }, 
    { "s=|setting=", "a setting", (m, v) => { /* do stuff */ } }, 
}; 

에 코드를 변경할 수 있습니다 그리고 그 희망 (심지어 코딩 모범 사용이 페이지의 끝에 ndesk here에서 예) 당신에게 당신이 원하는 기능의 종류를 제공해야합니다 .

희망 사항은 이전 답변보다 유용합니다.

+1

args []에서 문자열을 버킷으로 분할하는 것이 명령 행에서 "libraries"를 구문 분석하는 것이 전부라면 좋은 대답입니다. 그러나 당신의 대답으로, 묻는 사람은 여전히 ​​"-p"와 "-s"접두사 문자열을 스스로 가져와야합니다. (대체 양식/p, -p 또는 별명/project =, - project =는 처리되지 않습니다) 그리고 나서 그는 모든 설정에서 "="기호를 분석해야하며, 그 다음에 그는 모든 코드를 작성하여 명령 행 문서를 작성해야합니다. –

+0

@JeanHominal 귀하의 포인터와 질문을 구체적으로 반영하도록 업데이트되었습니다. – GMasucci

+1

사실, Mono.옵션은 NDesk.Options와 거의 같은 코드입니다 - 둘 다 다른 것과 같이 이식성이 있습니다 (Mono.Options의 코드에는 NDESK_OPTIONS 컴파일 변수가 있으며 클래스의 네임 스페이스를 변경하는 것만 볼 수 있습니다). 그러나 Mono.Options은 5 개월 전에 업데이트되었으며 NDesk.Options 페이지는 2008 년 이후로 이동하지 않은 것으로 확인되었습니다. Mono.Options에는 NDesk보다 약간 더 많은 기능이 있습니다. 옵션. –

0
class Program 
    { 
     static void Main(string[] args) 
     { 
      string cmd = "car.exe -ip 1.18.4.156 -port 123"; 
      string hostname = "localhost"; 
      string port = "5505"; 

      string[] array = cmd.Split(' '); 

      int hostnameIndex = Array.FindIndex(array, key => key == "-ip"); 
      int portIndex = Array.FindLastIndex(array, key => key == "-port"); 

      if (hostnameIndex != -1) 
      { 
       hostname = array[hostnameIndex + 1]; 
      } 

      if (portIndex != -1) 
      { 
       port = array[portIndex + 1]; 
      } 

      Console.WriteLine("ip :" + hostname); 
      Console.WriteLine("port :" + port); 

     } 
    }