怎么使用正则表达式完美匹配HTML标签?

转自腾讯前端博客:http://imweb.io/topic/56e804e…


匹配HTML标签嘛,感觉很简单的样子,我们的第一反应可能是:var pattern = /<[^>]+>/ 不过这样匹配可能存在的问题是:如果tag中含有>,上面的正则就不能正常匹配了。如: <input name=123 value=">" > https://sfault-image.b0.upaiyun.com/247/730/2477308083-58d34691bcbe1 虽然上面这种HTML的写法很少(sha)见(bi),但确实合法的。因此,简单的<[^>]+>就不能用了,需要想个聪明点的办法。 我们先来看一下HTML Tag中有什么规则:<...>中能够出现 引用文本(被单引号或双引号包裹的) 非引用形式的“其他文本”(包括除了>和引号之外的任何字符)

引用文本:HTML中的引文可以用双引号,也可以用单引号,但不允许嵌套转义的引号。

因此我们可以使用/("[^"]*"|'[^']*')/来匹配。

其他文本:除了>和引号之外的任意字符

可以使用/[^'">]/来匹配 现在可以得出匹配HTML Tag的正则表达式最终版!

var pattern = /<(“[^”]“|’[^’]‘|[^’”>])*>/

给这个正则表达式来点注释:

< # 开始的尖括号”<”
( # 任意数量的…
“[^”]*“ # 双引号字符串
| # 或者是…
‘[^’]*‘ # 单引号字符串
| # 或者是…
[^’”>] # “其他文本”
)* #
> # 结束的尖括号”>”

需要注意的是,我们不用”+”来修饰[^'">]的原因是([^'">]+)*可能会带来灾难性的后果。匹配次数呈指数级增长。比如:对于简单的目标字符串helloworld,是星号会迭代10次,每一次迭代中[^'">]+匹配一个字符?还是星号迭代3次,内部的[^'">]+分别匹配5、2、3个字符?或者2、3、1、4个字符?还是其他情况?这样会把正则引擎搞疯掉的啦!