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

时间:2014-03-19 22:26:24

标签: 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</p>

每个标题下的段落数量未知。我现在想要创建一个正则表达式模式来提取标题的所有(!)出现以及以下段落。我试过这个:(<p>Header</\p>.*?)<p>Header</\p>。但这只适用于每一场比赛。

使用<p>Header</p>分隔上一个匹配工作正常。但我需要在下一场比赛中获得同一段文字。但是,它不是'#34;再循环&#34;。一旦这段文字被用来划分旧的比赛,就不会再用它来开始新的比赛。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

Don't use regular expressions for parsing HTM L。使用一些HTML解析器,如HtmlAgilityPack(可从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;
}

用法:

var result = paragraphs.SplitBy(p => p == "Header");

对于您的示例HTML,它会返回

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

答案 1 :(得分:1)

如果您想使用REGEX,请在C#中使用Multiline Regex匹配选项试试这个。

(<p>Header</p>[\s\S]*?)(?=<p>Header</p>|\Z)

这是使用前瞻(?=...)进行检查,无论匹配后跟标记<p>Header</p>还是输入结尾\Z

答案 2 :(得分:0)

如果它的语法正确的XML(意味着它没有违反XML的最小结构规则),您可以简单地将其加载到Xmldocument并拉出你的位需要使用XPath expressions,或使用XSLT transform来获得您想要的内容。

为什么重新发明轮子?