js的正则分组问题

'target[0]'.replace(/\[([^\[\]]*)\]/g, '.$1.') // target.0.

这是30-seconds-of-code下object下的get函数里的一段。这里我看不懂这种正则写法为什么能匹配替换成功?希望高手给出比较浅显的代码引导我来理解这段代码。
我模仿原作者的版本:

'target[0]'.replace(/\[(\d+)\]/g, '.$1.')

但说实话我也不能深刻理解我的这个版本,我想我可能主要是卡在:1、分组的内容为什么能越界替换掉外层的方括号;2、原作者的分组内的代码为什么能匹配0?

阅读 2.2k
2 个回答

首先来从外到内分析一下他用到的正则语法:
1、\[\]: 普通字符匹配 [ 和 ],匹配到了吗?答案: 匹配到了。
2、(): 分组,replace函数的第二参数中的:$1,就是分组中的值
3、[]: 定义匹配的字符范围:^\[\], 什么范围呢?^在这里就是关键
4、^: 有两种用法:

  • 限定开头
  • 取反

以上语法介绍完了。很明显分组中的正则:[^\[\]*]的意思是匹配除[] 的以外的任意字符。也就是0,所以整个正则也就匹配到字符中的:[0], 然后replace方法将它替换成了第一个分组($1)中的值:0
关键点就是^[]中使用是取反的意思
工具看下正则的语义:

clipboard.png
红框中None of

我理解错了,replace替换的是整个匹配到的字符串,那我的版本是可以理解的,但原作者的版本我还是理解不了。我把原作的完整代码贴出来:

const get = (from, ...selectors) =>
  [...selectors].map(s =>
    s
      .replace(/\[([^\[\]]*)\]/g, '.$1.')
      .split('.')
      .filter(t => t !== '')
      .reduce((prev, cur) => prev && prev[cur], from)
  )
  const obj = { selector: { to: { val: 'val to select' } }, target: [1, 2, { a: 'test' }] };
get(obj, 'selector.to.val', 'target[0]', 'target[2][a]')  // ['val to select', 1, 'test']

可以看出原作的写法兼容性还更好。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题