我需要匹配所有这些开头标记:
<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][a-zA-Z0-9]*)[^>]*(?<!/)>
其他回答
<([a-z][^>\s]*)(?:\s+[^>]+)?>
此正则表达式将匹配由单个单词(例如<p>、<a>等)组成的开头标记,后跟零个或多个空格和任意数量的字符(除了>或空白),然后是结束>字符。它还会将标记与属性匹配,并且不会将标记与包含a-z以外字符的名称匹配。然而,它仍然不会匹配自动关闭标签。
正如许多人已经指出的那样,HTML不是一种常规语言,这会使解析变得非常困难。我的解决方案是使用整洁的程序将其转换为常规语言,然后使用XML解析器来使用结果。有很多好的选择。我的程序使用Java和jtidy库编写,将HTML转换为XML,然后Jaxen将其展开为结果。
尽管为此目的使用正则表达式并不合适和有效,但有时正则表达式为简单的匹配问题提供了快速解决方案,在我看来,将正则表达式用于琐碎的工作并不可怕。
有一篇关于匹配StevenLevithan编写的最内部HTML元素的权威博客文章。
虽然不能用正则表达式解析HTML的答案是正确的,但它们在这里并不适用。OP只想用正则表达式解析一个HTML标记,这可以用正则表达式完成。
不过,建议的正则表达式是错误的:
<([a-z]+) *[^/]*?>
如果你在正则表达式中添加了一些东西,通过回溯,它可能会被强制匹配像<a>>这样的愚蠢的东西,[^/]太宽容了。还要注意,<space>*[^/]*是冗余的,因为[^/]*也可以匹配空格。
我的建议是
<([a-z]+)[^>]*(?<!/)>
其中(?<!…)是(在Perl正则表达式中)后面的否定外观。它的意思是“a<,然后是一个单词,然后是任何不是a>的东西,最后一个可能不是a/,后面是>”。
请注意,这允许使用<a/>(就像原始的正则表达式一样),因此如果您需要更严格的限制,则需要构建正则表达式以匹配由空格分隔的属性对。
每当我需要从HTML文档中快速提取内容时,我都会使用Tidy将其转换为XML,然后使用XPath或XSLT来获取所需内容。在您的案例中,类似于:
//p/a[@href='foo']