正则表达式获取类似 xpath 的字符串中的每个项目,每个下标作为一个组

Regex to get each item in an xpath-like string, with each subscript as a group

我想采用类似 xpath 的字符串,例如:

a.b.c[2].d[123].e1[4].f88[5]

并将每个路径部分作为一个匹配项,将每个下标(“数组索引”)作为一个组,如下所示:

match 1: a
match 2: b
match 3: c, group 1: 123
match 4: e1, group 1: 4,
match 5: f88, group 1: 5

我尝试了以下方法(无效):

[^.]+(?:\[)*([0-9]+)*(?:\])*

根据我的理解,这个正则表达式的意思是:

  1. 首先,匹配除点以外的所有字符
  2. 然后,检查(但不要捕获)左方括号 - 它可能出现 0 次到无限次。
  3. 然后,检查任何数字,长度从 1 到无限 - 并作为一个组捕获。
  4. 然后,为右方括号再次执行 2。

但是没用。

我怎样才能让它发挥作用?

[^.]+(?:\[)*([0-9]+)*(?:\])*

“但它不起作用” 因为 +greedy 并且 consumes 点之前的所有字符。此外,每个下标是整体可选的,而不是逐个部分。

应用这些标准,这个表达式确实有效:

([^.\[]+)(?:\[(\d+)\])?

Regex101 Test

您试过的模式:

  • 您尝试的模式匹配太多,因为 negated character class [^.]+ 匹配除点以外的任何字符 1 次或多次,也可以匹配方括号。

  • 请注意,此表示法 (?:\[)*\[* 相同,并且匹配 0 次或多次左方括号

如果 \G 锚点 is supported,并且您只想从字符串的开头匹配示例字符串,您可以为您想要的数据使用 2 个捕获组,并匹配中间的点和方括号。

\G([^\][.\s]+)(?:\[(\d+)\])?\.?

模式匹配:

  • \G 断言位置在上一个匹配的末尾,或者在字符串的开头
  • ([^\][.\s]+) 捕获 组 1,匹配除 ] [ . 以外的 1+ 个字符或空白字符 (因为示例字符串中似乎没有任何空格)
  • (?:\[(\d+)\])? 可选匹配捕获 组 2 在匹配的方括号之间
  • \.? 匹配一个可选的点以继续对 \G anchor
  • 的连续匹配

Regex demo

如果字符串末尾不能有点,并且必须至少有 1 个点,您可以先从字符串的开头断言整个格式:

(?:^(?=[^.]+(?:\.[^.]+)+$)|\G(?!^))\.?([^\][.]+)(?:\[(\d+)\])?

Regex demo