当前位置:嗨网首页>书籍在线阅读

17-替换组

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

17.15 替换组

分组带来的一个好处是,可以利用它做一些更加复杂的替换。继续看HTML的例子,假如想去掉一个标签中除了href以外的内容。

let html = '<a class="nope" href="/yep">Yep</a>';
html = html.replace(/<a .*?(href=".*?").*?>/, '<a $1>');

正如反向引用中讲到的,所有的组都被分配了一个从1开始的数字。在这个正则表达式中,通过\1来引用第一个组;而在替换字符串上,用的是$1。注意,在这个表达式中使用懒惰量词是为了防止它在匹配时跨越多个 标签。不过,如果标签的href属性使用的是单引号而非双引号,也会匹配失败。

下面来扩展这个例子。希望保持class属性和href属性,仍旧删除其他元素:

let html = '<a class="yep" href="/yep" id="nope">Yep</a>';
html = html.replace(/<a .*?(class=".*?").*?(href=".*?").*?>/, '<a $2 $1>');

注意在这个正则表达式中,将class和href的顺序颠倒了一下,使得href始终先出现。这个表达式的问题在于class和href始终要保持相同的顺序,并且(就像之前提到的)一旦标签中的属性使用了单引号(而非双引号),就会匹配失败。我们将在下一节看到一个更为复杂的解决方案。

除了$1、$2、$3……这些组引用,还有$'(匹配项之前的所有内容)、$&(匹配目标本身)和$'(匹配项之后的所有内容)。如果想使用一个美元符号,可以使用$$:

const input = "One two three";
input.replace(/two/, '($`)');    // "One (One ) three"
input.replace(/\w+/g, '($&)');   // "(One) (two) (three)"
input.replace(/two/, "($')");    // "One ( three) three"
input.replace(/two/, "($$)");    // "One ($) three"

这些替换宏经常会被忽视,但是作者见过它们在一些非常聪明的解决方案中出现,所以不要忘记它们哦。