一个js正则表达式的问题?

var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
var value="<div/>";
value = value.replace( rxhtmlTag, "<$1></$2>" );
console.log(value);

这段代码的输出结果为:

<div></div>

为什么呢?看不懂代码,求javascript高手指点一下。

阅读 2.4k
1 个回答

(这段正则表达式怎么那么像jQuery源码中的呢?)
这个正则表达式的目的是将自闭合形式的标签修改成起始标签相应出现的形式。
即把"<div/>"修改成"<div></div>",
把"<div data-name='xxx'/>"修改成"<div data-name='xxx'></div>"的形式。

下面详细说明正则表达式含义。
/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([w:]+)[^>]*)/>/gi
1.整体可以看成//gi的形式
2.再剥开一层看到的是/<.*\/>/的形式
3.再仔细看到2中描述.*,更准确一点是(?!area|br|col|embed|hr|img|input|link|meta|param)(([w:]+)[^>]*)两部分
4.3中的左部分表示环视look-ahead向前看,但是具有否定意义
5.3中的右部分表示要匹配的内容,它是((.*).*)的一般形式
6.一般形式的正则表示,如.*,我希望题主能懂,不做多解释。

修饰符:
//g表示匹配全局匹配,有多个匹配到的,就有多个被替换,如

value = "<div/><div/>"
value.replace( rxhtmlTag, "<$1></$2>" );
//结果:"<div></div><div></div>"

//i表示忽略大小写匹配,如(略)
一般形式1:/<.*\/>/,这个就是匹配<div .../>这种标签形式的字符串
look-ahead部分:(?!area|br|col|embed|hr|img|input|link|meta|param)
这部分表示说右边不能这些area,br等情况,jQuery的中觉得像<input />这种形式不需要修改。
如:

value = "<input type='text' />"
value.replace( rxhtmlTag, "<$1></$2>" );
//结果:<input type='text' />

捕获分组:(([w:]+)[^>]*)
这里开始引入捕获分组概念,捕获分组和非捕获分组是有区别的(也没有必要细说)。
捕获分组有意义的地方在于可以被引用,如$1$2这里就是引用了捕获分组1和捕获分组2的意思。
(([w:]+)[^>]*)这里有两对括号,从左边往右,每对组成一个捕获分组,所以一共两个捕获分组,捕获分组1是整体(([w:]+)[^>]*),捕获分组2是([w:]+)
捕获分组2的要匹配的是w和(或):的多次出现的情况,+是量词表示匹配的次数,至少出现一次,如

re = /<[\w:]+\/>/
re.test("<i/>"); //true
re.test("</>"); false

引用捕获分组,相当于引用实际被匹配到的字符串,如题意

value = "<div xxx=yyy/>"
value = value.replace( rxhtmlTag, "<$1></$2>" );
//结果:"<div xxx=yyy></div>"

捕获分组1匹配到内容是div xxx=yyy,捕获分组2匹配到内容是div
所以replace方法的第二参数中刚好使用到他们,将他们分别填入$1$2

然后:[^>]*这部分也很关键,在前面捕获分组2匹配到那个标签tag后,这部分把后续完整的字符保留下来,当然像下面的情况就没有起到匹配替换的效果。

value = "<div xxxx=yyyy>/>"
value = value.replace( rxhtmlTag, "<$1></$2>" );
//结果:<div xxxx=yyyy>/>

正则表达式量词有?,+,*
一般形式2:.*

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题