【问题标题】:Why is C#'s Regex.Matches() returning all matches in a single Match object?为什么 C# 的 Regex.Matches() 在单个 Match 对象中返回所有匹配项?
【发布时间】:2015-11-08 09:29:54
【问题描述】:

我在使用 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# 的 regex.Matches 没有捕获 3 个实例,而是一个包含所有事件的单个实例。这是Matches 方法的预期行为吗?我一直在使用它,并且一直将所有事件作为单独的捕获。

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

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

【问题讨论】:

标签: regex html-parsing


【解决方案1】:

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

使用独特的正则表达式风格,所以我建议改用 在线测试器。例如:

但是,&lt;script.*&gt;[^&gt;]*&lt;\/script&gt; 模式应该返回几乎所有风格的相同匹配文本。

代码

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 代码中有 &gt; 符号(作为 IF 条件的一部分或在字符串中),它将失败。

不使用正则表达式解析 HTML 的原因有很多,因此请采纳以下建议:不要使用正则表达式。 相反,您可以使用 HTML Agility Pack(1) 编辑: 相反,我建议使用 @ 987654328@.

【讨论】:

  • 是的,我知道“如果您的 JavaScript 代码中有 &gt; 登录(这意味着不应该依赖这样的正则表达式,是的)。
  • 我正在尝试您的建议,并再次进行敏捷包装测试 :-)
  • 由于 HTML Agility Pack 既不维护也不兼容 HTML5,我强烈建议使用更好的解决方案。有很多(有些人可以看到@Veverke 的答案)。
【解决方案2】:

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

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

  • HTML 敏捷包
  • CsQuery
  • 锐角

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

【讨论】:

  • 感谢您为您选择的软件包做出贡献。我从来没有使用过后者,我会看看它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-07
  • 2014-12-23
  • 1970-01-01
相关资源
最近更新 更多