在空行C#之间匹配文本

时间:2017-01-27 23:56:45

标签: c# regex

我有一个像

这样的文字
rrr
ttt

yyyy
zzz
cc

iii
o

我需要在空行之间匹配块。所以,结果应该是:

0.
rrr
ttt

1.
yyyy
zzz
cc

2.
iii
o

尝试

var m = System.Text.RegularExpressions.Regex.Match(text, @"([a-zA-Z]+\r\n)+");

它不起作用。

5 个答案:

答案 0 :(得分:3)

我只是想补充一些解释:

  • Regex(@"(.+((\r\n)|$))+")稍短,也应与您的文本块匹配,因为:
    • .+匹配除换行符之外的所有内容
    • (\r\n)|$)匹配新行或字符串的结尾
    • (.+((\r\n)|$))+匹配多个非空行
  • 而不是拆分和重新组合,您只需使用text.Split(new[] { "\r\n\r\n" }, StringSplitOptions.RemoveEmptyEntries)
  • 即可

此外,还有关于正则表达式性能的讨论。我比较了m.rogalski,正则表达式(预编译)和带有BenchmarkDotNet的string.split解决方案的答案,这是一种常见的微基准解决方案。我没有将输出写入控制台,而是将其放入列表中。

以下是示例文本的基准测试结果

BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0
Processor=Intel(R) Pentium(R) CPU B970 2.30GHz, ProcessorCount=2
Frequency=2241012 Hz, Resolution=446.2270 ns, Timer=TSC
  [Host]     : Clr 4.0.30319.42000, 32bit LegacyJIT-v4.6.1586.0
  DefaultJob : Clr 4.0.30319.42000, 32bit LegacyJIT-v4.6.1586.0

           Method |      Mean |    StdDev |  Gen 0 | Allocated |
 ---------------- |---------- |---------- |------- |---------- |
       TestRegExp | 5.1306 us | 0.0402 us | 1.1607 |   1.41 kB |
        TestLists | 1.1866 us | 0.0106 us | 0.3395 |     408 B |       
  TestStringSplit | 1.3574 us | 0.0103 us | 0.6971 |     784 B |

我们能观察到什么?

  • regexp慢了五倍,需要十倍的内存
  • 字符串拆分需要更多内存,因为它会复制字符串
  • 使用stringreader
  • 实现最有效的解决方案

答案 1 :(得分:2)

您可以在阅读文件时执行此操作:

// create a placeholder for processed lines
List<List<string>> _output = new List<List<string>>();

using (StreamReader reader = new StreamReader(File.OpenRead(filePath)))
{
    int i = 0; // create indexer
    _output.Add(new List<string>()); // add new sequence
    _output.Last().Add(i.ToString() + "."); // insert sequence indexer
    string line = string.Empty;
    while( (line = reader.ReadLine()) != null)
    {
        if(string.IsNullOrWhiteSpace(line))
        {
            i++;
            _output.Add(newList<string>());
            _output.Last().Add(i.ToString() + ".");
        }
        else
        {
            _output.Last().Add(line);
        }
    }
}

然后您可以使用以下方法将其写入文本文件:

using (StreamWriter writer = new StreamWriter(File.OpenWrite(filePath)))
{
    foreach(List<string> lines in _output)
    {
        foreach(string line in lines)
        {
            writer.WriteLine(line);
        }
        writer.WriteLine(line);
    }
}

如果那不是文件(未指定)而是string,则可以使用StringReader代替StreamReaderStringWriter代替StreamWriter

对于其他想因为“非正则表达”答案或其他b而想要进行投票的人....

Make your comparison

答案 2 :(得分:1)

我会选择产生群组的简单解决方案:

private static IEnumerable<IEnumerable<string>> GetGroups(IEnumerable<string> source)
    {
        var grouped = new List<string>();
        foreach(var el in source)
        {
            if(!string.IsNullOrWhiteSpace(el))
                grouped.Add(el);
            else if(grouped.Any())
            {
                yield return grouped;
                grouped = new List<string>();
            }
        }

        if(grouped.Any())
            yield return grouped;

    }

用法:

    var input = @"rrr
ttt

yyyy
zzz
cc

iii
o";


        var res = GetGroups(input.Split(Environment.NewLine.ToCharArray()));
        foreach(var r in res)
        {
            Console.WriteLine(string.Join(",",r));
        }

小提琴:https://dotnetfiddle.net/xB87bZ

答案 3 :(得分:0)

简单,使用nested groups

using System.Text.RegularExpressions;

MatchCollection findings = new Regex(@"((.|(\n.))+)|((\n\n)((.|(\n.))+))").Matches(text);
for(int i = 0; i < findings.Count; i++) {
    int groupIndex = findings[i].Groups[1].Length > 0 ? 0 : 6;
    string match = findings[i].Groups[groupIndex].ToString();
    Console.WriteLine(i+".");
    Console.WriteLine(match);
}

您可以测试特定的正则表达式here。结果是在组1或6中(如上面的代码片段所示)。

我不知道为什么当前接受的答案是非正则表达式解决方案......

答案 4 :(得分:0)

你可以试试这个: string input = "your text here"; string reg = @"([a-zA-Z]+\r\n)+"; var m = (text, reg, RegexOptions.Multiline);