你真的掌握replace方法了吗?

161 阅读2分钟

语法

str.replace(regexp|substr, newSubStr|function)

该方法并不改变调用它的字符串本身,而只是返回一个新的替换后的字符串。

使用字符串作为参数(newSubStr)

替换字符串可以插入下面的特殊变量名:

变量名代表的值
$$插入一个 "$"。
$&插入匹配的子串。
$`插入当前匹配的子串左边的内容。
$'插入当前匹配的子串右边的内容。
$n假如第一个参数是 RegExp对象,并且 n 是个小于 100 的非负整数,那么插入第 n 个括号匹配的字符串。提示:索引是从 1 开始。如果不存在第 n 个分组,那么将会把匹配到到内容替换为字面量。比如不存在第 3 个分组,就会用“$3”替换匹配到的内容。
$<Name>这里Name 是一个分组名称。如果在正则表达式中并不存在分组(或者没有匹配),这个变量将被处理为空字符串。只有在支持命名分组捕获的浏览器中才能使用。

指定一个函数作为参数(function)

你可以指定一个函数作为第二个参数。在这种情况下,当匹配执行后,该函数就会执行。函数的返回值作为替换字符串。 (注意:上面提到的特殊替换参数在这里不能被使用。) 另外要注意的是,如果第一个参数是正则表达式,并且其为全局匹配模式,那么这个方法将被多次调用,每次匹配都会被调用

下面是该函数的参数:

变量名代表的值
match匹配的子串。(对应于上述的$&。)
p1,p2, ...假如 replace() 方法的第一个参数是一个RegExp对象,则代表第 n 个括号匹配的字符串。(对应于上述的$1$2 等。)例如,如果是用 /(\a+)(\b+)/ 这个来匹配,p1 就是匹配的 \a+p2 就是匹配的 \b+
offset匹配到的子字符串在原字符串中的偏移量。(比如,如果原字符串是 'abcd',匹配到的子字符串是 'bc',那么这个参数将会是 1)
string被匹配的原字符串。
NamedCaptureGroup命名捕获组匹配的对象

示例:

const str = 'x---x_aa123';
const result = str.replace(/(x_*)|(-)|\d+/g, function(match, p1, p2) {
  console.log('match: ' + match)
  if (p1) { console.log('p1: ' + p1); return p1.length*1}
  if (p2) { console.log('p2: ' + p2); return p2}
  return match*2
});
console.log('result:' + result)

// match: x
// p1: x
// match: -
// p2: -
// match: -
// p2: -
// match: -
// p2: -
// match: x_
// p1: x_
// match: 123
// result:1---2aa246

正则表达式 /(x_*)|(-)/gg 表示全局匹配,两个括号匹配的字符串分别用p1p2表示。如上所示,match代表匹配的所有集合,包含p1p2

利用replacelistdata里的val值倒序排列

let listdata = {
    val: 1,
    next: {
        val: 2,
        next: {
            val: 3,
            next: {
                val: 4,
                next: null
            }
        }
    }
}

看下答案

var re = /(.+)(\d+)(.+)(\d+)(.+)(\d+)(.+)(\d+)(.+)/g;
var str = JSON.stringify(listdata)
var newstr = str.replace(re, "result: $1$8$3$6$5$4$7$2$9");
console.log(newstr);
// result: {"val":4,"next":{"val":3,"next":{"val":2,"next":{"val":1,"next":null}}}}

此例使用字符串作为参数,$2$4$6$8匹配的是数字1、2、3、4。在替换字符串中将它们倒序插入即可。

格式化日期

思路:替换掉format字符串中的y M d H m s。之前一直云里雾里不太理解,有了思路之后豁然开朗。

/**
 * 
 * @param {string | Date} time 
 * @param {string} format 
 * @returns {string}
 */
const formatDate = (time, format) => {
  const date = time || new Date();
  const datemap = {
    y: date.getFullYear(),
    M: date.getMonth() + 1, //month
    d: date.getDate(), //date
    H: date.getHours(), //hours
    m: date.getMinutes(), //minutes
    s: date.getSeconds(), //seconds
  };
  for (var i in datemap) {
    if (datemap.hasOwnProperty(i)) {
      if (datemap[i] < 10) {
        datemap[i] = "0" + datemap[i];
      }
    }
  }
  format = format || "yyyy-MM-dd HH:mm:ss";
  const reg = new RegExp("y+|M+|d+|H+|m+|s+", "g");
  const result = format.replace(reg, (match) => {
    return datemap[match.charAt(0)];
  });
  return result;
};

console.log(formatDate(new Date())) // 2023-05-05 18:59:58
console.log(formatDate(new Date(), 'yyyy/MM/dd')) // 2023/05/05
console.log(formatDate(new Date(), 'yyyy-MM-dd')) // 2023-05-05

参考

正则表达式 - JavaScript | MDN (mozilla.org)

String.prototype.replace() - JavaScript | MDN (mozilla.org)