我需要匹配所有这些开头标记:
<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一次或多次,然后找到零个或多个空格,然后查找任何字符零次或多次,贪婪,除了/,然后查找大于
我有这个权利吗?更重要的是,你怎么看?
当前回答
虽然不能用正则表达式解析HTML的答案是正确的,但它们在这里并不适用。OP只想用正则表达式解析一个HTML标记,这可以用正则表达式完成。
不过,建议的正则表达式是错误的:
<([a-z]+) *[^/]*?>
如果你在正则表达式中添加了一些东西,通过回溯,它可能会被强制匹配像<a>>这样的愚蠢的东西,[^/]太宽容了。还要注意,<space>*[^/]*是冗余的,因为[^/]*也可以匹配空格。
我的建议是
<([a-z]+)[^>]*(?<!/)>
其中(?<!…)是(在Perl正则表达式中)后面的否定外观。它的意思是“a<,然后是一个单词,然后是任何不是a>的东西,最后一个可能不是a/,后面是>”。
请注意,这允许使用<a/>(就像原始的正则表达式一样),因此如果您需要更严格的限制,则需要构建正则表达式以匹配由空格分隔的属性对。
其他回答
如果您只是试图查找这些标记(没有解析的野心),请尝试以下正则表达式:
/<[^/]*?>/g
我在30秒内写下了它,并在这里进行了测试:http://gskinner.com/RegExr/
它匹配您提到的标记类型,而忽略您所说的要忽略的类型。
您希望第一个>前面不带/。请查看此处了解如何执行此操作的详细信息。这被称为消极的后顾。
然而,在这个示例文档中,这一天真的实现最终将与<bar/></foo>匹配
<foo><bar/></foo>
你能提供更多关于你试图解决的问题的信息吗?您是否以编程方式遍历标签?
我建议在PHP中使用QueryPath解析XML和HTML。它的语法与jQuery基本相同,只是在服务器端。
<([a-z][^>\s]*)(?:\s+[^>]+)?>
此正则表达式将匹配由单个单词(例如<p>、<a>等)组成的开头标记,后跟零个或多个空格和任意数量的字符(除了>或空白),然后是结束>字符。它还会将标记与属性匹配,并且不会将标记与包含a-z以外字符的名称匹配。然而,它仍然不会匹配自动关闭标签。
我同意解析XML,特别是HTML的正确工具是解析器,而不是正则表达式引擎。然而,正如其他人所指出的,有时使用正则表达式更快、更容易,并且如果您知道数据格式,就可以完成任务。
微软实际上有一节《.NET Framework中正则表达式的最佳实践》,专门讨论了“考虑输入源”。
正则表达式确实有局限性,但您是否考虑过以下问题?
在正则表达式方面,.NET框架是独一无二的,因为它支持平衡组定义。
请参见将平衡构造与.NET正则表达式匹配请参见.NET正则表达式:Regex和平衡匹配请参阅Microsoft关于平衡组定义的文档
因此,我相信您可以使用正则表达式解析XML。然而,请注意,它必须是有效的XML(浏览器对HTML非常宽容,并且允许HTML中有错误的XML语法)。这是可能的,因为“平衡组定义”将允许正则表达式引擎充当PDA。
引用上述第1条:
.NET正则表达式引擎如上所述,不能用正则表达式。但是,.NET正则表达式引擎提供了一些允许平衡构造辨识。(?<group>)-使用名称组。(?<-group>)-从捕获堆栈。(?(组)yes|no)-如果存在组,则匹配yes部分否则,名称组不匹配任何部分。这些构造允许.NET正则表达式模拟通过本质上允许简单版本的堆栈来限制PDA操作:推送、弹出和清空。简单的操作非常简单分别相当于递增、递减和比较为零。这允许.NET正则表达式引擎识别上下文无关语言的子集,特别是那些仅需要一个简单的计数器。这反过来允许非传统的.NET正则表达式,以识别各个正确平衡的构造。
考虑以下正则表达式:
(?=<ul\s+id="matchMe"\s+type="square"\s*>)
(?>
<!-- .*? --> |
<[^>]*/> |
(?<opentag><(?!/)[^>]*[^/]>) |
(?<-opentag></[^>]*[^/]>) |
[^<>]*
)*
(?(opentag)(?!))
使用标志:
单线IgnorePatternHitespace(如果折叠正则表达式并删除所有空格,则不需要)IgnoreCase(不需要)
正则表达式解释(内联)
(?=<ul\s+id="matchMe"\s+type="square"\s*>) # match start with <ul id="matchMe"...
(?> # atomic group / don't backtrack (faster)
<!-- .*? --> | # match xml / html comment
<[^>]*/> | # self closing tag
(?<opentag><(?!/)[^>]*[^/]>) | # push opening xml tag
(?<-opentag></[^>]*[^/]>) | # pop closing xml tag
[^<>]* # something between tags
)* # match as many xml tags as possible
(?(opentag)(?!)) # ensure no 'opentag' groups are on stack
您可以在一个更好的.NET正则表达式测试仪上尝试。
我使用了以下示例源:
<html>
<body>
<div>
<br />
<ul id="matchMe" type="square">
<li>stuff...</li>
<li>more stuff</li>
<li>
<div>
<span>still more</span>
<ul>
<li>Another >ul<, oh my!</li>
<li>...</li>
</ul>
</div>
</li>
</ul>
</div>
</body>
</html>
这找到了匹配项:
<ul id="matchMe" type="square">
<li>stuff...</li>
<li>more stuff</li>
<li>
<div>
<span>still more</span>
<ul>
<li>Another >ul<, oh my!</li>
<li>...</li>
</ul>
</div>
</li>
</ul>
尽管它实际上是这样的:
<ul id="matchMe" type="square"> <li>stuff...</li> <li>more stuff</li> <li> <div> <span>still more</span> <ul> <li>Another >ul<, oh my!</li> <li>...</li> </ul> </div> </li> </ul>
最后,我真的很喜欢杰夫·阿特伍德的文章:解析Html的Cthhulhu方式。有趣的是,它引用了这个问题的答案,目前有超过4万张选票。