replace方法

字符串有一个replace方法,该方法可用于将字符串中的一部分替换为另一个字符串。

  1. console.log("papa".replace("p", "m"));
  2. // → mapa

该方法第一个参数也可以是正则表达式,这种情况下会替换正则表达式首先匹配的部分字符串。若在正则表达式后追加g选项(全局,Global),该方法会替换字符串中所有匹配项,而不是只替换第一个。

  1. console.log("Borobudur".replace(/[ou]/, "a"));
  2. // → Barobudur
  3. console.log("Borobudur".replace(/[ou]/g, "a"));
  4. // → Barabadar

如果 JavaScript 为replace添加一个额外参数,或提供另一个不同的方法(replaceAll),来区分替换一次匹配还是全部匹配,将会是较为明智的方案。遗憾的是,因为某些原因 JavaScript 依靠正则表达式的属性来区分替换行为。

如果我们在替换字符串中使用元组,就可以体现出replace方法的真实威力。例如,假设我们有一个规模很大的字符串,包含了人的名字,每个名字占据一行,名字格式为“姓,名”。若我们想要交换姓名,并移除中间的逗号(转变成“名,姓”这种格式),我们可以使用下面的代码:

  1. console.log(
  2. "Liskov, Barbara\nMcCarthy, John\nWadler, Philip"
  3. .replace(/(\w+), (\w+)/g, "$2 $1"));
  4. // → Barbara Liskov
  5. // John McCarthy
  6. // Philip Wadler

替换字符串中的$1$2引用了模式中使用圆括号包裹的元组。$1会替换为第一个元组匹配的字符串,$2会替换为第二个,依次类推,直到$9为止。也可以使用$&来引用整个匹配。

第二个参数不仅可以使用字符串,还可以使用一个函数。每次匹配时,都会调用函数并以匹配元组(也可以是匹配整体)作为参数,该函数返回值为需要插入的新字符串。

这里给出一个小示例:

  1. let s = "the cia and fbi";
  2. console.log(s.replace(/\b(fbi|cia)\b/g,
  3. str => str.toUpperCase()));
  4. // → the CIA and FBI

这里给出另一个值得讨论的示例:

  1. let stock = "1 lemon, 2 cabbages, and 101 eggs";
  2. function minusOne(match, amount, unit) {
  3. amount = Number(amount) - 1;
  4. if (amount == 1) { // only one left, remove the 's'
  5. unit = unit.slice(0, unit.length - 1);
  6. } else if (amount == 0) {
  7. amount = "no";
  8. }
  9. return amount + " " + unit;
  10. }
  11. console.log(stock.replace(/(\d+) (\w+)/g, minusOne));
  12. // → no lemon, 1 cabbage, and 100 eggs

该程序接受一个字符串,找出所有满足模式“一个数字紧跟着一个单词(数字和字母)”的字符串,返回时将捕获字符串中的数字减一。

元组(\d+)最后会变成函数中的amount参数,而·(\w+)元组将会绑定unit。该函数将amount转换成数字(由于该参数是\d+`的匹配结果,因此此过程总是执行成功),并根据剩下 0 还是 1,决定如何做出调整。