从一道大厂面试题说说正则的子项吧,正则平时用的不少,但是…

230 阅读3分钟

 今天说说正则吧,平时用到的时候不少,但是可能大部分人都是直接搜索吧?“谁没事花时间写这个呢?直接搜索不香吗?”,你自己或者同事有没有这样说过呢?

首先得了解基本的匹配规则,这里就不说了,网上资料非常多,大家自行查找。

然后看看什么是子项,先从一道AL面试题来分析:

说明:写一个转换函数,把json对象的key值从下划线(Pascal)形式转为小驼峰(Camel)形式 示例:convert({“a_bc_def”: 1}); // 返回 {“aBcDef”: 1}

xuehuayu.cn/article/278…

分析:此题的考点是replace方法,和正则表达式

先举个栗子,看看这个方法怎么用:

var str = "a_bc_def"
function toCamel (str) {
  return str.replace(/_\w/g, function (a, b, c, d) {
    console.log(a, b, c, d)
  })
}
toCamel(str)
结果:
_b 1 a_bc_def undefined
_d 4 a_bc_def undefined

分析:

参数 a 代表 匹配到的字符串 参数 b 代表 匹配到的字符串的下标 参数 c 代表 整个字符串 至此,此题已经可解 但是,匹配到字符串中还有下划线,此时还不是最优解,能不能直接匹配到首字母呢

答案是肯定的,先看效果,换一种写法

var str = "a_bc_def"
function toCamel (str) {
  return str.replace(/_(\w)/g, function (a, b, c, d) {
    console.log(a, b, c, d)
  })
}
toCamel(str)
结果:
_b b 1 a_bc_def
_d d 4 a_bc_def

分析:

参数 a 代表 匹配到的字符串 参数 b 代表 匹配到的没有下划线的字符串 参数 c 代表 匹配到的字符串的下标 参数 d 代表 整个字符串 不同的地方,就是多写了个括号,下面来看看这个括号是个什么东西

正则表达式的子项(子表达式)

没错了,每个()中包含的部分叫做正则的子项(子表达式)

为了看明白,改一下上面的栗子,给下划线也加上括号,看看效果

var str = "a_bc_def"
function toCamel (str) {
  return str.replace(/(_)(\w)/g, function (a, b, c, d, e) {
    console.log(a, b, c, d, e)
  })
}
toCamel(str)
结果:
_b _ b 1 a_bc_def
_d _ d 4 a_bc_def

分析:

现在参数变成5个了 参数 a 代表 匹配到的字符串 参数 b 代表 匹配到的下划线 参数 c 代表 匹配到的没有下划线的字符串 参数 d 代表 匹配到的字符串的下标 参数 e 代表 整个字符串

由上,可以发现规律:

第1个参数表示: 匹配到的字符串 第2个参数表示: 匹配到的字符串的第1个子项 第3个参数表示: 匹配到的字符串的第2个子项 ……如果有多个子项,则依次类推 然后倒数第2个参数是:匹配到的字符串的下标 最后1个参数是:整个字符串

至此,分析完毕

此题解法是

var obj = {"a_bc_def": 1}

function toCamel (a) {
  return a.replace(/_(\w)/g, function(a, b){
    return b.toUpperCase()
  })
}

function convert (obj) {
  if (Object.prototype.toString.call(obj) !== '[object Object]') return obj
  let res = {}
  for (key in obj) {
    let newKey = toCamel(key)
    res[newKey] = obj[key]
  }
  return res
}

console.log(convert(obj)) // {aBcDef: 1}

拓展

replace的第二个参数可以是字符串,也可以是函数。如果它是字符串,那么每个匹配都将由字符串替换。 但是 replacement 中的 $ 字符具有特定的含义。如下表所示,它说明从模式匹配得到的字符串将用于替换。

字符替换文本
11、2、...、$99与 regexp 中的第 1 到第 99 个子表达式相匹配的文本。
$&与 regexp 相匹配的子串。
$`位于匹配子串左侧的文本。
$'位于匹配子串右侧的文本。
> 栗子 ```js let name = "Doe, John"; name = name.replace(/(\w+)\s*, \s*(\w+)/, "$2 $1"); console.log(name) // John Doe ```js ```js let name = '"a", "b"'; name = name.replace(/"([^"]*)"/g, "'$1'"); console.log(name) // 'a', 'b' ``` > 更好的写法 ```js // 将驼峰转为指定连接符 fromCamelCase (str, separator = '_') { return str.replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2').replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2').toLowerCase(); }, // 将下划线连接符转为驼峰形式 toCamelCase (str) { return str.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2, offset) => p2 ? p2.toUpperCase() : p1.toLowerCase()); }, ``` ![mp.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7d0495a0ec2243d88f3e780cf8a8867f~tplv-k3u1fbpfcp-watermark.image?)