为什么C#的Regex.Matches()会返回单个Match对象中的所有匹配项?

时间:2015-11-08 09:29:55

标签: regex html-parsing

我在使用C#中的正则表达式从html文本中获取所有<script>及其各自的结束</script>标记时遇到问题。

我创建了一个样本html,看起来像:

<html>
<head>
<title>
</title>

<script src="adasdsadsda.js"></script>
</head>

<body>
    <script type='javascript'>
        var a = 1 + 2;

        alert('a');
    </script>
</body>

<script></script>
</html>

我正在使用的正则表达式是:

<script.*>[^>]*<\/script>

我经常使用regexr来验证/测试我的正则表达式(强烈推荐它!)。它显示有问题的正则表达式捕获3次出现(正如我所期望的那样)。

但是C#&#39; regex.Matches没有捕获3个实例,而是一个包含所有实例的实例。这是Matches方法的预期行为吗?我一直在使用它,并将所有事件都作为一个单独的捕获。

为什么会发生这种情况?

P.S:在回答这个问题时,如果你想指出正则表达式不适合解析HTML,请解释为什么regexr和.NET的正则表达式给出不同的结果?他们有不同的正则表达式实现吗?

2 个答案:

答案 0 :(得分:1)

RegExr使用您浏览器的RegExp引擎进行匹配。它实现了不同的正则表达式。

使用独特的正则表达式风格,因此我建议使用在线测试人员。例如:

但是,模式<script.*>[^>]*<\/script>应该在几乎所有风格中返回相同的匹配文本。

<强>代码

string pattern = @"<script.*>[^>]*<\/script>";
var re = new Regex( pattern);
var text = @"
        <html>
        <head>
        <title>
        </title>

        <script src=""adasdsadsda.js""></script>
        </head>

        <body>
            <script type='javascript'>
                var a = 1 + 2;

                alert('a');
            </script>
        </body>

        <script></script>
        </html>
    ";


MatchCollection matches = re.Matches(text);
for (int mnum = 0; mnum < matches.Count; mnum++)
{   //loop matches
    Match match = matches[mnum];
    Console.WriteLine("Match #{0} - Value: {1}", mnum + 1, match.Value);
}

<强>输出

Match #1 - Value: <script src="adasdsadsda.js"></script>
Match #2 - Value: <script type='javascript'>
                        var a = 1 + 2;

                        alert('a');
                    </script>
Match #3 - Value: <script></script>

ideone demo

也就是说,如果您的JavaScript代码中有>符号(作为IF条件或字符串的一部分),则会失败。

有很多理由不用正则表达式解析HTML,所以请注意以下建议:不要使用正则表达式。 相反,您可以使用HTML Agility Pack (1) 编辑相反,我建议您使用一个HTML parser

答案 1 :(得分:1)

我将马里亚诺的答案标记为解决方案,但我将离开这里进一步研究的结果,这在选定的答案中未提及:

似乎最受欢迎的选项是按照受欢迎程度,以下nuget包:

  • Html Agility Pack
  • CsQuery
  • AngleSharp

我最终使用了AngleSharp,它比仍在维护/开发的CsQuery更具优势。