我需要匹配所有这些开头标记:
<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子集,你知道格式并且你只想提取一些值时,正则表达式可以是一个非常强大的工具。我这样做了数百次,几乎总是达到我想要的目的。
其他回答
我建议在PHP中使用QueryPath解析XML和HTML。它的语法与jQuery基本相同,只是在服务器端。
虽然不能用正则表达式解析HTML的答案是正确的,但它们在这里并不适用。OP只想用正则表达式解析一个HTML标记,这可以用正则表达式完成。
不过,建议的正则表达式是错误的:
<([a-z]+) *[^/]*?>
如果你在正则表达式中添加了一些东西,通过回溯,它可能会被强制匹配像<a>>这样的愚蠢的东西,[^/]太宽容了。还要注意,<space>*[^/]*是冗余的,因为[^/]*也可以匹配空格。
我的建议是
<([a-z]+)[^>]*(?<!/)>
其中(?<!…)是(在Perl正则表达式中)后面的否定外观。它的意思是“a<,然后是一个单词,然后是任何不是a>的东西,最后一个可能不是a/,后面是>”。
请注意,这允许使用<a/>(就像原始的正则表达式一样),因此如果您需要更严格的限制,则需要构建正则表达式以匹配由空格分隔的属性对。
无法使用正则表达式解析[X]HTML。因为正则表达式无法解析HTML。Regex不是一个可以用来正确解析HTML的工具。正如我之前多次在这里回答的HTML和正则表达式问题一样,正则表达式的使用不允许您使用HTML。正则表达式是一种不够复杂的工具,无法理解HTML所使用的构造。HTML不是一种正则语言,因此不能由正则表达式解析。Regex查询无法将HTML分解为有意义的部分。很多次,但我都不明白。即使是Perl使用的增强型不规则正则表达式,也无法完成解析HTML的任务。你永远不会让我崩溃。HTML是一种非常复杂的语言,它不能被正则表达式解析。甚至Jon Skeet也无法使用正则表达式解析HTML。每次你试图用正则表达式解析HTML时,这个邪恶的孩子都会痛哭流涕,而俄罗斯黑客则会在你的网络应用程序上进行攻击。用正则表达式解析HTML会将受污染的灵魂召唤到活人的领域。HTML和正则表达式就像爱情、婚姻和仪式性的杀婴。<center>无法保持它太晚了。正则表达式和HTML在同一概念空间中的合力会像水一样摧毁你的思想。如果你用正则表达式解析HTML,你就屈服于他们和他们的亵渎方式,这让我们所有人都要为一个名字无法在基本多语言平面中表达的人付出不人道的努力,他来了。HTML加正则表达式将使n当你观察时,你的心灵在恐惧的冲击中枯萎。基于x的HTML解析器是杀死StackOverflow的癌症,为时已晚,为时不晚,我们无法得救,因为一个chi͡ld的犯罪确保了regex将吞噬所有的活组织(除了它不能消耗的HTML,如前所预言的那样)亲爱的主,请帮助我们,任何人如何能在这场灾难中幸存下来,使用regex来解析HTML已经注定了人类将遭受永恒的可怕折磨使用正则表达式作为处理HTML的工具的安全漏洞在这个世界和c͒ͪo͛ͫ腐败实体(如SGML实体,但更腐败)的可怕领域之间建立了一个漏洞,这仅仅是对reg世界的一瞥用于HTML的ex解析器将他突然把一个程序员的意识带入了一个不断尖叫的世界,瘟疫般的slithy regex感染会我吞噬你的HTML解析器、应用程序和存在一直像Visual Basic一样,但更糟糕的是他来了,他来了就不来了对他来说s un̨hoğly radiańcé; destro҉ying all enli̍̈́س\836收紧,HTML标签lea͠ki̧n͘g fr ǫm̡yo͟我们的眼睛͢s̸̛l̕ik͏e liquid pain,re̸gular exp之歌压缩解析将退出用英语表达摩尔的声音来自sp的塔尔曼在这里我可以看到它,你可以看到它吗他终于揭穿了谎言人的全部都是LOS͖̩͇̗̪̏̈́T ALL I当他来的时候,他就失去了机会或渗透到我的脸上ᵒ天啊不不不O NΘ停止*̶͑̾̾ͫ͏̙̤g͛838̾ͫ;͇̫̑͆lot rȇͧ̌aͨl̘̝̙ͤ͂̾̆ZA̡͊͠LGΌISͮ;҉̛̯͈͕̹ͼ̱TO̶͇̺ͅƝȳ̳TH̘; Ë͖́̉\864 P͍̭O̚N̐Y̡Hͨ͊̽س̾̎801;̸̪̯E̾;̧̲̬͛ͪ̈́͘809;̨̦̱̹̭̰ͧC \877̙̝͖̏Oͮ͏7;͍M͊̒ͪ̚873; 876;Ỿ860;̲̖Ȇ∱̛̟͌S̨̥̫͎ͯ̿̔̀ͅ
您是否尝试过改用XML解析器?
主持人说明此帖子已锁定,以防止对其内容进行不当编辑。这篇文章看起来和它应该看起来完全一样——它的内容没有问题。请不要为我们的注意标记。
首先,回答一个直接的问题:正则表达式有一个bug,因为它会在任何地方排除带有斜线的标记,而不仅仅是在结尾。例如,它将排除这个有效的开头标记:<a href=“foo/bar.html”>,因为它在属性值中有一个斜杠。
我们可以解决这个问题,但更严重的是,这个正则表达式将导致误报,因为它还将匹配内部注释和cdata部分,其中相同的字符不表示有效的标记。例如:
<!-- <foo> -->
or
<![CDATA[ <foo> ]]>
尤其是嵌入脚本中的html字符串很可能会触发误报,JavaScript中经常使用<和>作为比较运算符也是如此。当然还有html的部分,这些部分用<!-->注释掉了。
因此,为了只匹配实际标记,您还需要能够跳过过去的注释和cdata部分。因此,您需要正则表达式来匹配注释和cdata,但只捕获开头标记。这仍然可以使用rexep,但它变得更加复杂,例如:
(
<!-- .*? --> # comment
| <!\[CDATA\[ .*? \]\]> # CData section
| < \w+ ( "" [^""]* "" | ' [^']* ' | [^>/'""] )* /> # self-closing tag
| (?<tag> < \w+ ( "" [^""]* "" | ' [^']* ' | [^>/'""] )* > ) # opening tag - captured
| </ \w+ \s* > # end tag
)
这仅适用于符合HTML兼容性准则的XHTML。如果您想处理任意XHTML,还应该处理处理指令和内部DTD,因为它们也可以嵌入误报。如果您还想处理HTML,还有其他复杂的问题,比如<script>-标记。如果您还想处理无效的HTML,则会变得更加复杂。
鉴于复杂性,我不建议走这条路。相反,寻找一个现成的(X)HTML解析库,它可以解决您的问题。
解析器通常在后台使用正则表达式(或类似的表达式)将文档拆分为“标记”(doctype、开始标记、结束标记、文本内容等)。但其他人会为您调试和测试这些正则表达式!根据解析器的类型,它可以通过匹配开始标记和结束标记来进一步构建元素的树结构。这几乎肯定会为您节省大量时间。
要使用的精确解析器库取决于您的语言和平台以及您正在解决的任务。如果您需要访问实际的标记子字符串(例如,如果您正在为HTML编写语法高亮),则需要使用SAX样式的解析器,该解析器直接公开语法标记。
如果您只执行标记匹配以手动构建元素的语法树,那么DOM解析器将为您完成这项工作。但是DOM解析器不公开底层的标记语法,因此无法解决您描述的确切问题。
您还应该考虑是否需要解析无效的HTML。这是一项复杂得多的任务,但在野生网络上,大多数HTML实际上是无效的。类似Pytons html5lib的东西可以解析无效的HTML。
在我看来,你试图匹配结尾没有“/”的标签。试试看:
<([a-zA-Z][a-zA-Z0-9]*)[^>]*(?<!/)>