首页 > 解决方案 > 解释和格式化用户输入

问题描述

我正在为我的软件设计一个命令行解释器,并且需要能够格式化用户输入。目前我有一个基本上用空格分割所有内容的系统,问题是我不需要在双引号内分割任何内容。

正如您可能知道的那样,我当前的实现不能很好地处理引用路径。

这是我当前的解释和格式化逻辑(包含在一个非静态方法中,当用户按下回车键时会调用该方法,以防有人想知道):

 var command = ConsoleInput.Text;
                ConsoleInput.Text = String.Empty;

                string command_main = command.Split(new char[] { ' ' }).First();
                string[] synatx = command.Split(new char[] { ' ' }).Skip(1).ToArray();

                if (lCommands.ContainsKey(command_main))
                {
                    Action<string[]> commandfunction;
                    lCommands.TryGetValue(command_main, out commandfunction);
                    commandfunction(synatx);
                }
                else
                    ConsoleOut($"Invalid Command - {command_main} {string.Join(" ", synatx)}"); 

我需要引用路径作为单个参数,而不是按间距分割。例如,(免责声明:这只是一个示例,而不是实际代码)

这是我不想要 的:输入:“这是一个测试”和更多文本,结果是这样的:syntax[0] = "this syntax[1] = is,依此类推.

预期的结果将是(我想要发生的): syntax[0] = "this is a test" syntax[1] = 和 syntax[2] = some,依此类推。

我卡在这里,有人有解决方案吗?谢谢你。

标签: c#string

解决方案


这是一个解决方案。它是一个组合在一起的状态机,可以处理可能包含空格的引用字符串。它丢弃参数之间无关的空格,并将双引号视为单个双引号(但没有任何特殊含义;就好像它是任何其他字符)。

 public IEnumerable<string> ParseLine(string toParse)
 {
     var result = new List<string>();
     bool inQuotedString = false;
     bool parsingDoubleQuote = false;
     bool inWhiteSpace = false;
     int length = toParse.Length;
     var argBuffer = new StringBuilder();

     for (var index = 0; index < length; ++index)
     {
         //if looking ahead for a double quote succeeded, just add the quote to the current arguemnt
         if (parsingDoubleQuote)
         {
             parsingDoubleQuote = false;
             argBuffer.Append('"');
             //and we are done with this character, so...
             continue;  //done with this character, time to just loop again
         }

         if (toParse[index] == '"')
         {
             inWhiteSpace = false;
             //look ahead one character to see if there's a double quote
             if (index < length - 1 && toParse[index + 1] == '"')
             {
                 parsingDoubleQuote = true;
                 continue;      //done with this character, time to just loop again
             }

             if (!inQuotedString)
             {
                 inQuotedString = true;
                 continue; //done with this character, time to just loop again
             }
             else
             {
                 //it's not a double quote, and we are in quotes string, so
                 inQuotedString = false;
                 //we don't add the buffer to the output args until a space or the end, so
                 continue;      //done with this character, time to just loop again
             }
         }
         //if we are here, there's no quote, so...
         if (toParse[index] == ' ' || toParse[index] == '\t')
         {
             if (inQuotedString)
             {
                 argBuffer.Append(toParse[index]);
                 continue;    //done with this character, time to just loop again
             }
             if (inWhiteSpace)
             {
                 //nothing to do
                 continue;     //out of the for loop
             }
             else
             {
                 inWhiteSpace = true;
                 if (argBuffer.Length > 0)
                 {
                     result.Add(argBuffer.ToString());
                     argBuffer.Clear();
                     continue;       //done with this character, time to just loop again
                 }
             }
         }
         else
         {
             inWhiteSpace = false;
             //no quote, no space, so...
             argBuffer.Append(toParse[index]);
             continue;     //done with this character, time to just loop again
         }
     }   //end of for loop
     if (argBuffer.Length > 0)
     {
         result.Add(argBuffer.ToString());
     }
     return result;
 }

我已经对其进行了粗略的测试——你会想要更努力地测试它


推荐阅读