正则表达式使用换行符分割字符串(除非它在双引号之间)

时间:2016-03-09 18:16:01

标签: c# regex split newline double-quotes

我正在做一些分隔文件处理。我需要做的第一件事是获得所有"线"。获取每一行后,我可以根据指定的分隔符进行拆分。因此,为了得到我需要使用各种线路指定(\ r \ n,\ r,\ n)分割字符串的行。以下是工作,直到我在双引号中遇到换行符:

return content.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);

因此,如果您考虑以下文本(我的原始文本使用双引号转义双引号,使用\"而不是""),其中每一行由其中一个行指定分隔,并且该行中的每个字段/列由管道" |"分隔。字符:

string s = "row1 col1|\"row1 \"\"col2a\"\"\r\nrow1 col2b\"|row1 col3\nrow2 col1|\"row2 \"\"col2a\"\"\rrow2 \"\"col2b\"\"\"|row2 col3\r\nrow3 col1|\"row3 col2a\nrow3 col2b\"|row3 col3";

等于以下字符串:

row1 col1 |" row1"" col2a"" {CRLF} row1"" col2b""&#34 ; | row1 col3 {CRLF} row2 col1 |" row2"" col2a"" {CRLF} row2"" col2b"&#34 ;" | row2 col3 {CRLF} row3 col1 |" row3 col2a {CRLF} row3 col2b" | row3 col3

使用我的原始方法拆分上述内容会产生5行:

string[] result = s.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);

但我想使用行分隔符(\ r \ n,\ r,\ n)分割上面的内容以产生3行:

result[0] == "row1 col1|\"row1 \"\"col2a\"\"\r\nrow1 col2b\"|row1 col3"
result[1] == "row2 col1|\"row2 \"\"col2a\"\"\rrow2 \"\"col2b\"\"\"|row2 col3"
result[2] == "row3 col1|\"row3 col2a\nrow3 col2b\"|row3 col3"

有没有人有幸运行正则表达式分割线(除了引号外)?

这是我最终得到的结果,感谢Alan:

public string[] GetLines (string fileContent) {
    Regex regex = new Regex(@"^([^""\r\n]*(?:(?:""[^""]*"")*[^""\r\n]*))", RegexOptions.Multiline);
    MatchCollection matchCollection = regex.Matches(fileContent);
    string[] result = new string[matchCollection.Count];
    for (int i = 0; i < matchCollection.Count; i++) {
        Match match = matchCollection[i];
        result[i] = match.Value;
    }
    return result;
}

2 个答案:

答案 0 :(得分:4)

我会使用Matches()代替Split()

Regex r = new Regex(@"(?m)^[^""\r\n]*(?:(?:""[^""]*"")+[^""\r\n]*)*");
MatchCollection m = r.Matches(s);

内部部分(?:(?:"[^"]*")+匹配可能包含转义引号的双引号字符串。整个正则表达式匹配可能包含一个或多个双引号字符串的行。请注意,内部字符类([^"])可以匹配\r\n,其中外部字符类([^"\r\n])明确排除它们。行起始锚点(多行模式中的^)可防止实际匹配之间的虚假空匹配。

这是一个demo。 (它在PCRE中,但我也在.NET中测试过它。)

答案 1 :(得分:0)

您可以尝试以下正则表达式:

var fieldSeparator = "|";
var strRx = $@"""[^""\r\n]*""{fieldSeparator}[^|]+(?:\s*)";

var rx = new Regex(strRx);
var data = "row1 col1|\"row1 \\\"col2a\\\"\r\nrow1 \\\"col2b\\\"\"|row1 col3\nrow2 col1|\"row2 col2a\rrow2 col2b\"";

var m = rx.Match(data);

while (m.Success)
{
    Console.WriteLine(m.Value);
    m = m.NextMatch();
}

只需将fieldSeparator值替换为您要使用的字段分隔符。

上面的代码片段产生以下输出:

row1 col1
"row1 \"
col2a\"
row1 \"col2b\""
row1 col3
row2 col1
row2 col2b"