正则表达式匹配不在 HTML 评论中的任何内容

Regex to match anything not in an HTML comment

首先让我说,我知道你不应该用正则表达式解析 HTML。我不是,我只是有一个极端情况,评论正在进入我的内容,不幸的是我无法改变它。

我一直在绞尽脑汁想为 .NET 设计一个正则表达式模式,它可以匹配任何不属于 HTML 评论的内容。例如:

foo<!--abc-->bar

应该匹配 "foo" 和 "bar"。

foobar

应该匹配"foobar"(没有注释,所以匹配所有)。

<!--foo-->

不应产生任何匹配项,因为评论中没有任何内容。

我可以很容易地使用正则表达式 <!--.*?--> 来匹配注释,但是根据我的程序规范,在这种情况下我不能简单地删除它们,我需要匹配注释中没有的任何内容。我能够想到或在网上找到的每一种尝试排除评论的方法最终都会选择所有内容(因为评论的开始和结束不是匹配的开始和结束),或者找到不需要的匹配项。例如:

foo<!--abc-->bar

使用正则表达式 ((?!<!--.*?-->).)*(通过使用否定前瞻简单地否定正则表达式来查找评论),我得到 4 个匹配项:第一个是正确匹配的 "foo",然后是第二个和第四个匹配项显示为空白字符串(我不确定为什么),第三个匹配项是“!--abc-->bar”,因为简单地删除“<”在技术上满足条件。使最后一个 * 量词变懒似乎使情况变得更糟,返回 17 个空白字符串匹配。我尝试了一些其他方法,比如使用负面环视来排除评论,但它们都陷入了我不确定如何解决的类似问题。

我还尝试了这个问题的公认答案中的正则表达式:Regex to strip anything that isn't an html comment;但不幸的是,这包括匹配中评论的 <!----> 部分,如果我没看错,我认为它不会匹配其中没有评论的字符串。我试图修改它以解决我的用例的这些问题,但没有取得任何成功...

编辑

在从问题中退一步并重新考虑我的需求之后,我意识到我实际上不需要匹配所有不属于评论的文本。我真的只需要知道是否有任何非空白文本不属于评论的一部分,在内容的任何地方,使用 Regex.IsMatch 方法和 SingleLine 选项。为此,以下正则表达式应该可以解决问题:

(?!^(\s*<!--([^-]*|-[^-]*|--[^>]*)-->\s*)+$)^.*\S.*$

由于这彻底改变了问题并立即回答了它,我不确定现在正确的协议是什么......但是除非提出更好的建议,否则我想我会把这个问题留几个几天以防万一有人发现我的正则表达式有问题,如果没有人发现我会自己回答并关闭问题。

如果匹配和捕获变得复杂,在某些情况下 a simple "trick" can help:
Match what you don't want (on left side of an alternation) | or capture 您需要什么。

你不想要的是评论:<!--.*?-->

捕获任何字符,这不会开始打开评论:|((?:(?!<!--).)+)
lookahead防止跳过<!--) 并抓取第一个捕获组的捕获。

(?s)<!--.*?-->|((?:(?!<!--).)+)

(?s) 用于 single-line mode (dot also matches newlines). See this demo at regexstorm

在 PCRE 正则表达式中,可以通过 use of (*SKIP)(*F) verbs (demo) 在不捕获组的情况下完成。