【问题标题】:C# - Regular Expression to split string on spaces, unless a double quote is encounteredC# - 正则表达式在空格上拆分字符串,除非遇到双引号
【发布时间】:2011-03-09 19:33:41
【问题描述】:

这个帖子和我想要的很相似:Regular Expression to split on spaces unless in quotes

但我需要一些我无法弄清楚的额外规则: - 上面的线程确实在空格上拆分,除非它们在双引号中。但是,它也会在标点符号上分裂。我需要双引号内的任何内容作为一个实体。

例如:
/Update setting0 value="new value" /Save 应该返回
/更新
设置0
价值=
新值 (我不在乎它是否修剪引号)
/保存

/Import "C:\path\file.xml" "C:\path_2\file_2.xml" /Exit 应该返回
/导入
C:\path\file.xml (我不在乎它是否修剪引号)
C:\path_2\file_2.xml
/退出

我最终使用了上面线程中的这个表达式:

(?<=")\w[\w\s]*(?=")|\w+|"[\w\s]*"

有人可以帮我调整一下吗?谢谢!

【问题讨论】:

    标签: c# regex


    【解决方案1】:

    我没有在 C# 中尝试过,但在 Excel 中没有尝试过 VBA,但它可能会有所帮助。我也将双引号更改为单引号。无论如何,这是正则表达式

    文字:

    /Update setting0 value='new value' /Save

    正则表达式:

    ('{1}(\w|\s|:|\\|\.)+'{1}|\w)+
    

    结果:

    更新

    设置0

    价值

    '新值'

    保存

    文字:

    /导入 'C:\path\file.xml' 'C:\path_2\file_2.xml' /退出

    结果:

    导入

    'C:\path\file.xml'

    'C:\path_2\file_2.xml'

    退出

    【讨论】:

    • 一旦我将表达式中的单引号替换为双引号,这将非常有效。感谢您提供如此简洁的解决方案!
    • ('{1}(\w|\s|:|\\|\.)+'{1}|(/|\w))+ 这个版本应该返回 \Import 而不是进口。我刚刚在正则表达式的末尾将 \w 更改为 (/|\w)。
    • 哈哈,是的,我刚刚对此做了一个调整并测试了它:...|(/?\w)+
    【解决方案2】:

    这是一个通常无法使用正则表达式解决的问题。相反,您可以编写一个简单的解析器,它需要一行,读取每个字符,然后当它遇到空格并且不在引号内时,它会获取当前子字符串并将其添加到列表中:

    public static string[] ParseLine(string line)
            {
                var insideQuotes = false;
    
                var parts = new List<string>();
    
                var j = 0;
    
                for (var i = 0; i < line.Length; i++)
                {
                    switch (line[i])
                    {
                        case '"':
                             insideQuotes = !insideQuotes;
                             break;
                        case ' ':
                             if (!insideQuotes)
                             {
                                 parts.Add(line.Substring(j, i - j));
                                 j = i + 1;
                             }
                             break;
                        default:
                             continue;
                    }
                }
    
                return parts.ToArray();
            }
    

    但是请注意,这不会像引号内的转义引号一样处理。

    【讨论】:

      【解决方案3】:

      如果有偶数个双引号且没有转义引号,则此方法有效:

      ^
      \s*
      (?:
          (?:
              ([^\s"]+)
              |
              "([^"]*)"
          )
          \s*
      )+
      $
      

      【讨论】:

        【解决方案4】:
        var matches = Regex.Matches("/Update setting0 value=\"new value\" /Save", "\\G(?:(\"[^\"]*\"?|[^ \"]+)|[ ]+)");
        
        foreach (Match match in matches) {
            foreach (Capture capture in match.Groups[1].Captures) {
                Console.WriteLine(capture);
            }
        }
        

        如果你不想有引号(所以"new value"变成new value

        var matches = Regex.Matches("/Update setting0 value=\"new value\" /Save", "\\G(?:\"(?<1>[^\"]*)\"?|(?<1>[^ \"]+)|[ ]+)");
        

        第二个\" 之后的? 用于捕获未闭合的引号。

        【讨论】:

          【解决方案5】:

          只是我对eulerfx 发布的内容的修改版本。这个:

          应该产生原始问题中要求的结果(“关于主题”也是如此)。

          结果中不包含引号

          不只在结果中包含空格

          在引号内的任何空白处拆分结果

          通过在循环后添加任何剩余的内容来处理缺少的结束引号

          修剪结果,除非在引号内。

          我主要是为了解析 IMAP 列表结果每行的最后 2 部分。

              public static string[] ParseLine(string line)
              {
                  var insideQuotes = false;
                  var start = -1;
          
                  var parts = new List<string>();
          
                  for (var i = 0; i < line.Length; i++)
                  {
                      if (Char.IsWhiteSpace(line[i]))
                      {
                          if (!insideQuotes)
                          {
                              if (start != -1)
                              {
                                  parts.Add(line.Substring(start, i - start));
                                  start = -1;
                              }
                          }
                      }
                      else if (line[i] == '"')
                      {
                          if (start != -1)
                          {
                              parts.Add(line.Substring(start, i - start));
                              start = -1;
                          }
                          insideQuotes = !insideQuotes;
                      }
                      else
                      {
                          if (start == -1)
                              start = i;
                      }
                  }
          
                  if (start != -1)
                      parts.Add(line.Substring(start));
          
                  return parts.ToArray();
              }
          

          【讨论】:

            猜你喜欢
            • 2010-10-07
            • 2020-11-06
            • 1970-01-01
            • 2021-11-14
            • 2016-06-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-09-02
            相关资源
            最近更新 更多