代码如下:
'z/yy'.replace(/\/(y|z)|y|z/g, function(name, index) {
console.log(index, name.length);
return name == 'y' || name == 'z' ? 'a' : name;
});
正确输出:a/ya
'z/yy'.replace(/\/(y|z)|\1/g, function(name, index) {
console.log(index, name.length);
return name == 'y' || name == 'z' ? 'a' : name;
});
错误输出:z/yy
请问为什么呢?
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
@皓矾 的console解释的比较清楚了,唯一不同意的地方是|\1不是匹配所有字符串,而是0长空字符。console里可以看出来。
这里/\/(y|z)|\1/是分为两个正则分别匹配的:
1. \/(y|z) 捕获组1是括号中y|z匹配的内容。比如/(y|z)\1/ 匹配yy,zz,但是不匹配yz
2. \1 捕获组1未定义
所以2中的\1不会如你所想的匹配y或z
比较符合你意图的写法可能是
/\/?(y|z)/
这两个正则是不等价的。
第一个
/\/(y|z)|y|z/g,分解开来是\/(y|z)或y或z。所以,对于字符串z/yy,第一个字符z匹配,被替换为a,/y符合但不等于y或z,所以原样输出为/y,最后一个z同理替换为a。第二个
/\/(y|z)|\1/g,比较复杂,展开来说。在此之前,先根据MDN的文档重写下函数,因为题主的参数不太正确:
其中,
matcher是匹配的子字符串,p1是捕捉组匹配的子字符串,既(y|z)捕捉到的,offset是偏移值,str是原字符串。执行结果如下:
一步步来,
z/yy,matcher为空,未匹配。/yy,matcher为/y,捕捉到y。但题主的返回值判断的是matacher与y和z的比较,所以原样返回/y。y,matcher为空,未匹配。matcher为空,未匹配。关键在第三行,对于字符串'y',正则仍然是
/\/(y|z)|\1/g,而不是题主所想的/\/(y|z)|(y|z)/g,所以不匹配。顺带研究了下这种
|\1写法的正则,这种写法貌似会匹配任何字符串,甚至空字符串。比如:甚至:
所以,最好还是别这样写……