我需要匹配所有这些开头标记:
<p>
<a href="foo">
但不是这些:
<br />
<hr class="foo" />
我想出了这个,想确保我做得对。我只是在捕捉a-z。
<([a-z]+) *[^/]*?>
我相信上面写着:
找到一个小于,然后查找(并捕获)a-z一次或多次,然后找到零个或多个空格,然后查找任何字符零次或多次,贪婪,除了/,然后查找大于
我有这个权利吗?更重要的是,你怎么看?
我需要匹配所有这些开头标记:
<p>
<a href="foo">
但不是这些:
<br />
<hr class="foo" />
我想出了这个,想确保我做得对。我只是在捕捉a-z。
<([a-z]+) *[^/]*?>
我相信上面写着:
找到一个小于,然后查找(并捕获)a-z一次或多次,然后找到零个或多个空格,然后查找任何字符零次或多次,贪婪,除了/,然后查找大于
我有这个权利吗?更重要的是,你怎么看?
当前回答
如果您只需要标记名,那么应该可以通过正则表达式执行此操作。
<([a-zA-Z]+)(?:[^>]*[^/] *)?>
应该做你需要的事。但我认为“莫里茨”的解决方案已经很好了。我一开始没看到。
对于所有反对者:在某些情况下,使用正则表达式是有意义的,因为这可能是最简单、最快捷的解决方案。我同意一般情况下不应该用正则表达式解析HTML。
但是当你有一个HTML子集,你知道格式并且你只想提取一些值时,正则表达式可以是一个非常强大的工具。我这样做了数百次,几乎总是达到我想要的目的。
其他回答
在我看来,你试图匹配结尾没有“/”的标签。试试看:
<([a-zA-Z][a-zA-Z0-9]*)[^>]*(?<!/)>
正如许多人已经指出的那样,HTML不是一种常规语言,这会使解析变得非常困难。我的解决方案是使用整洁的程序将其转换为常规语言,然后使用XML解析器来使用结果。有很多好的选择。我的程序使用Java和jtidy库编写,将HTML转换为XML,然后Jaxen将其展开为结果。
的确,在编程时,在处理HTML时,最好使用专用解析器和API,而不是正则表达式,尤其是在准确性至关重要的情况下(例如,如果您的处理可能涉及安全问题)。然而,我并不认为XML风格的标记永远不应该用正则表达式来处理。在某些情况下,正则表达式是一个很好的工具,例如在文本编辑器中进行一次性编辑,修复损坏的XML文件,或者处理看起来像但不太像XML的文件格式。有一些问题需要注意,但它们并非不可逾越,甚至不一定相关。
像<([^>“']|”[^“]*”|'[^']*')*>这样的简单正则表达式通常足够好,例如我刚才提到的那些情况。这是一个天真的解决方案,但它确实允许在属性值中使用未编码的>符号。如果您正在查找,例如,表标签,您可以将其调整为</?表\b([^>“']|”[^“]*”|'[^']*')*>。
为了了解更“高级”的HTML正则表达式会是什么样子,以下内容在模拟真实世界的浏览器行为和HTML5解析算法方面做了相当出色的工作:
</?([A-Za-z][^\s>/]*)(?:=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)|[^>])*(?:>|$)
以下内容与相当严格的XML标记定义相匹配(尽管它没有考虑XML名称中允许的全部Unicode字符集):
<(?:([_:A-Z][-.:\w]*)(?:\s+[_:A-Z][-.:\w]*\s*=\s*(?:"[^"]*"|'[^']*'))*\s*/?|/([_:A-Z][-.:\w]*)\s*)>
当然,这些不考虑周围的上下文和一些边缘情况,但如果您真的想处理这些问题(例如,通过在另一个正则表达式的匹配项之间进行搜索),也可以处理这些问题。
在一天结束时,使用最适合该作业的工具,即使该工具恰好是正则表达式。
OP似乎没有说他需要用标签做什么。例如,他需要提取内部文本,还是只检查标签?
我坚定地认为正则表达式不是万能的文本解析器。我已经编写了大量的文本解析代码,包括用于解析HTML标记的代码。
虽然我确实对正则表达式不太在行,但我认为正则表达式太死板,很难维护这种解析。
尽管为此目的使用正则表达式并不合适和有效,但有时正则表达式为简单的匹配问题提供了快速解决方案,在我看来,将正则表达式用于琐碎的工作并不可怕。
有一篇关于匹配StevenLevithan编写的最内部HTML元素的权威博客文章。