我需要匹配所有这些开头标记:

<p>
<a href="foo">

但不是这些:

<br />
<hr class="foo" />

我想出了这个,想确保我做得对。我只是在捕捉a-z。

<([a-z]+) *[^/]*?>

我相信上面写着:

找到一个小于,然后查找(并捕获)a-z一次或多次,然后找到零个或多个空格,然后查找任何字符零次或多次,贪婪,除了/,然后查找大于

我有这个权利吗?更重要的是,你怎么看?


当前回答

我建议在PHP中使用QueryPath解析XML和HTML。它的语法与jQuery基本相同,只是在服务器端。

其他回答

您希望第一个>前面不带/。请查看此处了解如何执行此操作的详细信息。这被称为消极的后顾。

然而,在这个示例文档中,这一天真的实现最终将与<bar/></foo>匹配

<foo><bar/></foo>

你能提供更多关于你试图解决的问题的信息吗?您是否以编程方式遍历标签?

虽然不能用正则表达式解析HTML的答案是正确的,但它们在这里并不适用。OP只想用正则表达式解析一个HTML标记,这可以用正则表达式完成。

不过,建议的正则表达式是错误的:

<([a-z]+) *[^/]*?>

如果你在正则表达式中添加了一些东西,通过回溯,它可能会被强制匹配像<a>>这样的愚蠢的东西,[^/]太宽容了。还要注意,<space>*[^/]*是冗余的,因为[^/]*也可以匹配空格。

我的建议是

<([a-z]+)[^>]*(?<!/)>

其中(?<!…)是(在Perl正则表达式中)后面的否定外观。它的意思是“a<,然后是一个单词,然后是任何不是a>的东西,最后一个可能不是a/,后面是>”。

请注意,这允许使用<a/>(就像原始的正则表达式一样),因此如果您需要更严格的限制,则需要构建正则表达式以匹配由空格分隔的属性对。

OP似乎没有说他需要用标签做什么。例如,他需要提取内部文本,还是只检查标签?

我坚定地认为正则表达式不是万能的文本解析器。我已经编写了大量的文本解析代码,包括用于解析HTML标记的代码。

虽然我确实对正则表达式不太在行,但我认为正则表达式太死板,很难维护这种解析。

在shell中,可以使用sed解析HTML:

图灵.sed编写HTML解析器(作业)???利润


相关(为什么不应该使用正则表达式匹配):

如果你这么喜欢正则表达式,为什么不嫁给它们?正则表达式:现在有两个问题黑客攻击stackoverflow.com的HTML清理器

正如许多人已经指出的那样,HTML不是一种常规语言,这会使解析变得非常困难。我的解决方案是使用整洁的程序将其转换为常规语言,然后使用XML解析器来使用结果。有很多好的选择。我的程序使用Java和jtidy库编写,将HTML转换为XML,然后Jaxen将其展开为结果。