繁体   English   中英

在空行之间匹配文本C#

[英]Match text between empty lines C#

我有一个像

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)+");

没用

我只想添加一些解释:

  • Regex(@"(.+((\\r\\n)|$))+")短一些,它也应该与您的文本块匹配,因为:
    • .+匹配除换行符以外的所有内容
    • (\\r\\n)|$)匹配新行或字符串的结尾
    • (.+((\\r\\n)|$))+匹配多条非空行
  • 无需拆分和重新text.Split(new[] { "\\r\\n\\r\\n" }, StringSplitOptions.RemoveEmptyEntries) ,您只需使用text.Split(new[] { "\\r\\n\\r\\n" }, StringSplitOptions.RemoveEmptyEntries)

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

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

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可以实现最有效的解决方案

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

// 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

对于因“ non-regex”答案或其他一些原因而希望投票的所有人。...

进行比较

我将寻求产生小组的简单解决方案:

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

简单,使用嵌套组

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM