转自腾讯前端博客:http://imweb.io/topic/56e804e...
匹配HTML标签嘛,感觉很简单的样子,我们的第一反应可能是:var pattern = /<[^>]+>/
不过这样匹配可能存在的问题是:如果tag中含有>
,上面的正则就不能正常匹配了。如: <input name=123 value=">" >
虽然上面这种HTML的写法很少(sha)见(bi),但确实合法的。因此,简单的<[^>]+>
就不能用了,需要想个聪明点的办法。 我们先来看一下HTML Tag中有什么规则:<...>
中能够出现 引用文本(被单引号或双引号包裹的) 非引用形式的“其他文本”(包括除了>
和引号之外的任何字符)
引用文本:HTML中的引文可以用双引号,也可以用单引号,但不允许嵌套转义的引号。
因此我们可以使用/("[^"]*"|'[^']*')/
来匹配。
其他文本:除了>和引号之外的任意字符
可以使用/[^'">]/
来匹配 现在可以得出匹配HTML Tag的正则表达式最终版!
var pattern = /<(“[^”]“|’[^’]*’|[^’”>])>/
给这个正则表达式来点注释:
< # 开始的尖括号”<”
( # 任意数量的…
“[^”]*“ # 双引号字符串
| # 或者是…
‘[^’]*‘ # 单引号字符串
| # 或者是…
[^’”>] # “其他文本”
)* #
> # 结束的尖括号”>”
需要注意的是,我们不用”+”来修饰[^'">]
的原因是([^'">]+)*
可能会带来灾难性的后果。匹配次数呈指数级增长。比如:对于简单的目标字符串helloworld,是星号会迭代10次,每一次迭代中[^'">]+
匹配一个字符?还是星号迭代3次,内部的[^'">]+
分别匹配5、2、3个字符?或者2、3、1、4个字符?还是其他情况?这样会把正则引擎搞疯掉的啦!