2012-02-10 50 views
1

我正在寻找一种算法/库来解析这个命令行:命令行(CSC样编译)解析

var cmd = "foo /option:value /option2:valueof /etc:.. baa /t:4 etc xd"; 

到:

foo => { "option", "value" }, 
     { "option2", "valueof" }, 
     {"etc", ".."}, 
baa => {"t", "4"}, 
etc => {"xd", ""}, 

我在“纯模式”尝试(类C)只是使用if和for。但是正则表达式或linq的解决方案非常值得赞赏。

我的代码(不工作):

var cmd = "foo /option:value /option2:valueof /etc:.. baa /t:4 etc xd"; 
      var keys = new Dictionary<string, Dictionary<string,string>>(); 

      for (int pos = 0, len = cmd.Length; pos < len; pos++) 
      { 
       StringBuilder buffer = new StringBuilder(); 
       char c = cmd[pos]; 

       if (c == '/') 
       { 
        StringBuilder optionName = new StringBuilder(); 
        StringBuilder optionValue = new StringBuilder(); 

        do 
        { 
         c = cmd[pos++]; 

         if (c == ':') 
         { 
          do 
          { 
           c = cmd[pos++]; 
           optionValue.Append(c); 

          } while (c != '/' || c != ' '); 
         } 
         else 
         { 
          optionName.Append(c); 
         } 

        } while (c != ' '); 

        keys.Add(buffer.ToString(), 
         new Dictionary<string, string> 
         { 
          {optionName.ToString(), optionValue.ToString()} 
         }); 
       } 
      } 

它提前给予Index was outside the bounds of the array.

感谢。

+0

选项值中是否可以有空格?如果是这样,你可以通过将它们用引号括起来来逃避它们吗?参数可以没有选择地发生吗?一个选项可以没有价值吗?是否有一个原因,你需要尝试解析一条线上的三个命令?回答这些问题将帮助我们回答您的问题。 – 2012-02-10 18:37:49

回答

2

当然,还有库来处理命令行解析(SO recommends NDesk, but I haven't personally used it)。

我会使用string.Split()通过字符逐字符遍历字符串。

  var tokenCmd = cmd.Split(' '); 
      string currentKey = ""; 

      foreach (var token in tokenCmd) 
      { 
       if ((char.IsLetterOrDigit(token[0])) && 
        (!keys.ContainsKey(currentKey)) || 
        (keys[currentKey].Any())) 
       { 
        currentKey = token; 
        keys.Add(currentKey, 
          new Dictionary<string, string>()); 
       } 
       else 
       { 
        var splitToken = new[] { token, "" }; 

        if (token.Contains(':')) 
        { 
         splitToken = token 
          .Replace("/", "") 
          .Split(':'); 
        } 

        keys[currentKey].Add(splitToken[0], 
             splitToken[1]); 
       } 
      } 
1

变化:

} while (c != '/' || c != ' '); 

到:

} while (c != '/' && c != ' '); 
0

如果你能保持保持命令行分离(他们在你输入VAR柏油在一起),并保留了ARGS进来的String []对象类型的话,我认为这是机器人,你”寻找:

static void Main(string[] args) 
{ 
    Hashtable parsedArgs = new Hashtable(); 
    args.ToList().ForEach(x => { 
     int dpos = x.IndexOf(":"); 
     if (dpos > -1) 
      parsedArgs[x.Substring(1, dpos - 1)] = x.Substring(dpos + 1); 
     else 
      parsedArgs[x.Substring(1)] = true; 
    }); 
} 

编辑:修改成Linq成一个Hashtable如下所示。在我的原始答案中,Hashtable比使用更优雅的(少代码)KeyValuePair <>更容易。