我需要匹配所有这些开头标记:
<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是Chomsky Type 2语法(上下文无关语法),正则表达式是ChomskyType 3语法(正则语法)。由于第2类语法从根本上比第3类语法更复杂(请参见乔姆斯基层次结构),因此不可能实现这一点。
但很多人会尝试,有些人甚至会声称成功,但直到其他人发现错误并将你彻底搞砸。
其他回答
<\s*(\w+)[^/>]*>
各部分解释如下:
<:起始字符
\s*:标签名称前可能有空格(难看,但可能)。
(\w+):标记可以包含字母和数字(h1)。嗯,w也与“_”匹配,但我想它不会伤害你。如果好奇,请改用([a-zA-Z0-9]+)。
[^/>]*:除了>和/直到关闭>
>:关闭>
不相关的
对于那些低估了正则表达式的人来说,他们说正则表达式的功能和正则语言一样强大:
anbanban不是规则的,甚至不是上下文无关的,可以与^(a+)b\1b\1匹配$
反向引用FTW!
下面是XML/XTML的PCRE正则表达式,它是根据简化的EBNF语法定义构建的:
/
(?(DEFINE)
(?<tag> (?&tagempty) | (?&tagopen) ((?&textnode) | (?&tag) | (?&comment))* (?&tagclose))
(?<tagunnested> (?&tagempty) | (?&tagopen) ((?&textnode) | (?&comment))* (?&tagclose))
(?<textnode> [^<>]+)
(?<comment> <!--([\s\S]*?)-->)
(?<tagopen> < (?&tagname) (?&attrlist)? (?&ws)* >)
(?<tagempty> < (?&tagname) (?&ws)* (?&attrlist)? (?&ws)* \/>)
(?<tagclose> <\/ (?&tagname) (?&ws)* >)
(?<attrlist> ((?&ws)+ (?&attr))+)
(?<attr> (?&attrunquoted) | (?&attrsinglequoted) | (?&attrdoublequoted) | (?&attrempty))
(?<attrempty> (?&attrname))
(?<attrunquoted> (?&attrname) (?&ws)* = (?&ws)* (?&attrunquotedvalue))
(?<attrsinglequoted> (?&attrname) (?&ws)* = (?&ws)* ' (?&attrsinglequotedvalue) ')
(?<attrdoublequoted> (?&attrname) (?&ws)* = (?&ws)* " (?&attrdoublequotedvalue) ")
(?<tagname> (?&alphabets) ((?&alphabets) | (?&digits))*)
(?<attrname>(?&alphabets)+((?&alphabets)|(?&digits)|[:-]) )
(?<attrunquotedvalue> [^\s"'=<>`]+)
(?<attrsinglequotedvalue> [^']+)
(?<attrdoublequotedvalue> [^"]+)
(?<alphabets> [a-zA-Z])
(?<digits> [0-9])
(?<ws> \s)
)
(?&tagopen)
/x
这说明了如何为上下文无关语法构建正则表达式。您可以通过将最后一行的匹配从(?&tagopen)更改为例如(?&tagunnested)来匹配定义的其他部分
真正的问题是:你应该这样做吗?
对于XML/XTML,共识是否定的!
感谢尼基奇提供了这个想法。
您希望第一个>前面不带/。请查看此处了解如何执行此操作的详细信息。这被称为消极的后顾。
然而,在这个示例文档中,这一天真的实现最终将与<bar/></foo>匹配
<foo><bar/></foo>
你能提供更多关于你试图解决的问题的信息吗?您是否以编程方式遍历标签?
Try:
<([^\s]+)(\s[^>]*?)?(?<!/)>
它与您的类似,但最后一个>不能在斜杠之后,也接受h1。
这可能会:
<.*?[^/]>
或不带结束标记:
<[^/].*?[^/]>
HTML解析器上的火焰大战是怎么回事?HTML解析器必须解析(并重建!)整个文档,然后才能对搜索进行分类。在某些情况下,正则表达式可能更快/更优雅。我的2美分。。。