C# - 正则表达式在空格上拆分字符串,除非遇到双引号

时间:2011-03-09 19:33:42

标签: c# regex

此主题非常类似于我想要的内容:Regular Expression to split on spaces unless in quotes

但我需要一些我无法弄清楚的额外规则: - 上面的线程会在空格上分割,除非它们是双引号。但是,它也会在标点符号上分开。我需要双引号内的任何东西保持为一个整体。

例如:
/更新设置0值=“新值”/保存应返回
/更新
setting0
值=
新值(我不在乎是否修剪报价)
/保存

/导入“C:\ path \ file.xml”“C:\ path_2 \ file_2.xml”/退出应该返回
/导入
C:\ path \ file.xml (我不在乎是否关闭引号)
C:\ PATH_2 \ file_2.xml
/退出

我最终在上面的帖子中使用了这个表达式:

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

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

5 个答案:

答案 0 :(得分:3)

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

文本:

/更新设置0值='新值'/保存

正则表达式:

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

结果:

<强>更新

<强> setting0

<强>值

'新值'

保存

文本:

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

结果:

导入

<强> 'C:\路径\ file.xml'

<强> 'C:\ PATH_2 \ file_2.xml'

退出

答案 1 :(得分:0)

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

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();
        }

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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>[^ \"]+)|[ ]+)");

第二个?之后的\"是要捕获未公开的引号。

答案 4 :(得分:0)

只是eulerfx发布的修改版本。这一个:

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

结果中不包含引号

仅在结果中不包含空格

在任何不在引号内的空格上分割结果

通过添加循环后留下的任何内容来处理缺少的结束引用

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

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

    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();
    }