C# 具有多个匹配项的正则表达式:模式应分隔旧匹配项并开始新匹配项

C# 具有多个匹配项的正则表达式:模式应分隔旧匹配项并开始新匹配项,c#,regex,C#,Regex,我有一段HTML代码,看起来类似于: <p>Header</p> <p>some text</p> <p>some more text</p> <p>Header</p> <p>only one paragraph</p> <p>Header</p> <p>some text</p> <p>some more text

我有一段HTML代码,看起来类似于:

<p>Header</p>
<p>some text</p>
<p>some more text</p>
<p>Header</p>
<p>only one paragraph</p>
<p>Header</p>
<p>some text</p>
<p>some more text</p>
标题

一些文本

更多的文字

标题

只有一段

标题

一些文本

更多的文字

每个标题下的段落数目不详。我现在想创建一个正则表达式模式来提取标题的所有(!)事件以及以下段落。我试过:
(Header.*?Header
)。但这只适用于每一场比赛

使用
标题

划界上一个匹配可以正常工作。但我需要在下一场比赛中有同样的文字。然而,它不是“回收”的。一旦这段文字被用于分隔旧的匹配,它将不再用于开始新的匹配

有什么想法吗?

L.使用一些HTML解析器,比如(可从NuGet获得)。例如,提取所有段落:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html_string);
var paragraphs = doc.DocumentNode.SelectNodes("//p").Select(p => p.InnerText);
以下任务是字符串的简单处理列表。您可以创建扩展方法将段落序列拆分为块:

public static IEnumerable<List<T>> SplitBy<T>(
    this IEnumerable<T> source, Func<T, bool> separator)
{
    List<T> batch = new List<T>();

    using (var iterator = source.GetEnumerator())
    {
        while (iterator.MoveNext())
        {
            if (separator(iterator.Current) && batch.Any())
            {
                yield return batch;
                batch = new List<T>();
            }

            batch.Add(iterator.Current);
        }
    }

    if (batch.Any())
        yield return batch;
}
对于示例HTML,它返回

[
  [ "Header", "some text", "some more text" ],
  [ "Header", "only one paragraph" ],
  [ "Header", "some text", "some more text" ]
]
L.使用一些HTML解析器,如(可从NuGet获得)。例如,提取所有段落:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html_string);
var paragraphs = doc.DocumentNode.SelectNodes("//p").Select(p => p.InnerText);
以下任务是字符串的简单处理列表。您可以创建扩展方法将段落序列拆分为块:

public static IEnumerable<List<T>> SplitBy<T>(
    this IEnumerable<T> source, Func<T, bool> separator)
{
    List<T> batch = new List<T>();

    using (var iterator = source.GetEnumerator())
    {
        while (iterator.MoveNext())
        {
            if (separator(iterator.Current) && batch.Any())
            {
                yield return batch;
                batch = new List<T>();
            }

            batch.Add(iterator.Current);
        }
    }

    if (batch.Any())
        yield return batch;
}
对于示例HTML,它返回

[
  [ "Header", "some text", "some more text" ],
  [ "Header", "only one paragraph" ],
  [ "Header", "some text", "some more text" ]
]
L.使用一些HTML解析器,如(可从NuGet获得)。例如,提取所有段落:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html_string);
var paragraphs = doc.DocumentNode.SelectNodes("//p").Select(p => p.InnerText);
以下任务是字符串的简单处理列表。您可以创建扩展方法将段落序列拆分为块:

public static IEnumerable<List<T>> SplitBy<T>(
    this IEnumerable<T> source, Func<T, bool> separator)
{
    List<T> batch = new List<T>();

    using (var iterator = source.GetEnumerator())
    {
        while (iterator.MoveNext())
        {
            if (separator(iterator.Current) && batch.Any())
            {
                yield return batch;
                batch = new List<T>();
            }

            batch.Add(iterator.Current);
        }
    }

    if (batch.Any())
        yield return batch;
}
对于示例HTML,它返回

[
  [ "Header", "some text", "some more text" ],
  [ "Header", "only one paragraph" ],
  [ "Header", "some text", "some more text" ]
]
L.使用一些HTML解析器,如(可从NuGet获得)。例如,提取所有段落:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html_string);
var paragraphs = doc.DocumentNode.SelectNodes("//p").Select(p => p.InnerText);
以下任务是字符串的简单处理列表。您可以创建扩展方法将段落序列拆分为块:

public static IEnumerable<List<T>> SplitBy<T>(
    this IEnumerable<T> source, Func<T, bool> separator)
{
    List<T> batch = new List<T>();

    using (var iterator = source.GetEnumerator())
    {
        while (iterator.MoveNext())
        {
            if (separator(iterator.Current) && batch.Any())
            {
                yield return batch;
                batch = new List<T>();
            }

            batch.Add(iterator.Current);
        }
    }

    if (batch.Any())
        yield return batch;
}
对于示例HTML,它返回

[
  [ "Header", "some text", "some more text" ],
  [ "Header", "only one paragraph" ],
  [ "Header", "some text", "some more text" ]
]

如果您希望使用正则表达式,请使用C#中的
多行正则表达式
匹配选项尝试使用此正则表达式

(标题

[\s\s]*?)(?=标题

|\Z)

这是使用lookahead
(?=…)
检查匹配后是否有标记
标题

或在输入的末尾
\Z

如果您希望使用正则表达式,请使用C++中的
多行正则表达式
匹配选项尝试此操作

(标题

[\s\s]*?)(?=标题

|\Z)

这是使用lookahead
(?=…)
检查匹配后是否有标记
标题

或在输入的末尾
\Z

如果您希望使用正则表达式,请使用C++中的
多行正则表达式
匹配选项尝试此操作

(标题

[\s\s]*?)(?=标题

|\Z)

这是使用lookahead
(?=…)
检查匹配后是否有标记
标题

或在输入的末尾
\Z

如果您希望使用正则表达式,请使用C++中的
多行正则表达式
匹配选项尝试此操作

(标题

[\s\s]*?)(?=标题

|\Z)

这是使用lookahead
(?=…)
检查匹配后是否有标记
标题

,或者在输入的末尾
\Z
是否是语法正确的XML(这意味着它没有违反XML的最小结构规则),您可以简单地将其加载到
Xmldocument
中,然后取出所需的位,或者使用一个


为什么要重新发明轮子?

如果它是语法正确的XML(也就是说它不违反XML的最小结构规则),您只需将其加载到
Xmldocument
中,然后取出所需的位,或者使用


为什么要重新发明轮子?

如果它是语法正确的XML(也就是说它不违反XML的最小结构规则),您只需将其加载到
Xmldocument
中,然后取出所需的位,或者使用


为什么要重新发明轮子?

如果它是语法正确的XML(也就是说它不违反XML的最小结构规则),您只需将其加载到
Xmldocument
中,然后取出所需的位,或者使用


为什么要重新发明轮子?

同样的问题。我需要将标题和以下段落分组。这个问题与HTML无关。问题仍然是一样的,即使
标记不见了。@Jan I通过处理解析的段落更新了解决方案。有用的链接也为这项工作增添了不少乐趣。但我一直在寻找萨布吉的答案。这对我来说非常合适。@Jan,如果你愿意的话-我的回答也会产生预期的结果。另外,我强烈建议您阅读第一个链接同样的问题。我需要将标题和以下段落分组。这个问题与HTML无关。问题仍然是一样的,即使
标记不见了。@Jan I通过处理解析的段落更新了解决方案。有用的链接也为这项工作增添了不少乐趣。但我一直在寻找萨布吉的答案。这对我来说非常合适。@Jan,如果你愿意的话-我的回答也会产生预期的结果。另外,我强烈建议您阅读第一个链接同样的问题。我需要将标题和以下段落分组。这个问题与HTML无关。问题仍然是一样的,即使
标记不见了。@Jan I通过处理解析的段落更新了解决方案。有用的链接也为这项工作增添了不少乐趣。但我一直在寻找萨布吉的答案。这对我来说非常合适。@Jan,如果你愿意的话-我的回答也会产生预期的结果。另外,我强烈建议您阅读第一个链接同样的问题。我需要将标题和以下段落分组。这个问题与HTML无关。问题依然存在