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

Why is C#'s Regex.Matches() returning all matches in a single Match object?

我在 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 到 validate/test 我的正则表达式(强烈推荐!)。它显示有问题的正则表达式捕获了 3 次(正如我预期的那样)。

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

为什么我的情况会发生这种情况?

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

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

uses a unique regex flavor, so I'd suggest using a 在线测试人员。例如:

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

代码

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 敏捷包(1). edit: Instead, I recommend using a HTML parser.

我将 Mariano 的答案标记为解决方案,但我将进一步研究的结果留在这里,所选答案中未提及:

似乎最受欢迎的选项是(按受欢迎程度排序)以下 nuget 包:

  • Html 敏捷包
  • CsQuery
  • 锐角

我最终使用了 AngleSharp,它比 CsQuery 的优势仍然是 maintained/developed。