用正则将"obj.p1.p2.arr1[2].arr2[0].p3"转化为数组

659 阅读2分钟

给你一个字符串

s = "obj.p1.p2.arr1[2].arr2[0].p3"

如何将其转换成数组

arr = ["obj", "p1", "p2", "arr1", "2", "arr2", "0", "p3"]

给一个正则解法

arr = s.match(/((?<=[\.\[\]])|^)[^\.\[\]]+((?=![\.\[\]])|&)/g)

不急...来一步一步分析

step1

首先这一定是一个全局匹配

arr = s.match(//g)

step2

先介绍2个概念:(?<=p)和(?=p)

前者匹配的是模式p右边的位置,后者匹配的是模式p左边的位置

可以参考 JS正则表达式完整教程(略长) 这篇文章理解这2个概念

举个例子来理解这2个东西,比如说,我们要把

s1 = 'xyz'

变成

s2 = 'x-y-z'

用上面2个东西怎么实现呢?很简单,把x的右边的位置和z左边的位置都替换成一个'-'

s2 = s1.replace(/(?<=x)|(?=z)/g, '-')

回到正题上来,我们要匹配的模式是用文字来说就是,一堆东西,

  1. 既有字符"."或者"["或者"]"在这堆东西的右边
  2. 又有字符"."或者"["或者"]"在这堆东西的左边

考虑到开头和结尾,应该说:

  1. 既有字符"."或者"["或者"]"或者开头的位置在这堆东西的右边
  2. 又有字符"."或者"["或者"]"或者结尾的位置在这堆东西的左边

所以我们的答案应该分成3个部分

arr = s.match(/(规则1对应的位置)(要提取的属性)(规则2对应的位置)/g)

第一个规则翻译成正则就是

(?<=[\.\[\]])|^

第二个规则翻译成正则

(?=[\.\[\]])|&

所以最终的答案现在是下面这样,尽管它还不完整,但已经很接近啦

arr = s.match(/((?<=[\.\[\]])|^)(要提取的属性)((?=[\.\[\]])|&)/g)

step3

要提取的属性是什么呢? 显然不能包含字符"."或者"["或者"]",翻译成正则就是:

[^\.\[\]]+

step4

拼到一起,就是

arr = s.match(/((?<=[\.\[\]])|^)[^\.\[\]]+((?=![\.\[\]])|&)/g)

下课!

等会

点个赞呗?