正则表达式 - 重复捕获组

19

我正在尝试找出如何在以下url字符串中重复一个捕获组,该字符串包含逗号分隔值:

id=1,2;name=user1,user2,user3;city=Oakland,San Francisco,Seattle;zip=94553,94523;

我正在使用此RegExp,它返回我想要的结果,除了值,因为它们是动态的,即url参数中可能有2、3、4等用户,想知道是否可以为每个值创建一个捕获组,而不是将user1,user2,user3作为一个捕获组。

RegExp: (^|;|:)(\w+)=([^;]+)*

这是在线演示,使用RegExp

示例输出:

  • Group1 - (分号,冒号)
  • Group2 - (关键字,例如id,name,city,zip)
  • Group3 - (value1)
  • Group4 - (value2)*如果存在
  • Group5 - (value3)*如果存在
  • Group6 - (value4)*如果存在

等等...根据我之前解释的动态值。

问题:我使用*循环重复模式的表达式有什么问题?


1
你期望的输出是什么?我认为这可以在不使用正则表达式的情况下完成。 - ibrahim mahrir
1
你期望得到这样的结果吗:{ "id": ["1", "2"], "name": ["user1", "user2", "user3"], "city": ["Oakland", "San Francisco", "Seattle"], "zip": ["94553", "94523"] } - ibrahim mahrir
@ibrahimmahrir 我在上面给出了示例输出,这些值是动态的,例如 user1,user2 等等... 所以基本上想要每个值都在自己的 捕获组 中。 - Jordan Davis
1
不!我说的是最终输出,而不是正则表达式的输出。你希望最终数据是什么样子? - ibrahim mahrir
这是你想要做的吗?https://regex101.com/r/2HQ8dv/2 - 0m3r
@0m3r 一点也不。 - Jordan Davis
2个回答

24
正则表达式不支持你尝试的操作。当引擎第二次进入捕获组时,它会覆盖第一次捕获的内容。考虑一个简单的例子(感谢regular-expressions.info):/(abc|123)+/'abc123'中使用。它将匹配"abc",然后看到加号并再次尝试匹配"123"。输出中的最终捕获组将是"123"。
无论您尝试什么模式,这种情况都会发生,而任何设置的限制只是更改了Regex何时接受字符串。考虑/(abc|123){2}/。这将接受带有捕获组为“123”的“abc123”,但不接受'abc123abc'。将捕获组放置在另一个捕获组中也无效。创建捕获组就像创建变量一样。它只能有一个值,并且后续值会覆盖先前的值。您永远无法拥有比括号对数更多的捕获组(当然可以少于括号对数)。
那么一个可能的修复方法是将字符串按 ';' 分隔,然后将每个分隔出来的字符串再按 '=' 分隔,最后将等号右边的内容按 ',' 分隔。这样可以得到 [['id', '1', '2'], ['name', 'user1', ...], ['city', ...], ['zip', ...]]
function (str) {
  var afterSplit = str.split(';|:');
  afterSplit.pop() // final semicolon creates empty string
  for (var i = 0; i < afterSplit.length; i++) {
    afterSplit[i] = afterSplit[i].split('=');
    afterSplit[i][1] = afterSplit[i][1].split(','); // optionally, you can flatten the array from here to get something nicer
  }
  return afterSplit;
}

尽管捕获组不会重复,但在某些情况下,您可以简单地复制捕获组。例如,假设我正在解析源代码,并且我想匹配类声明以获取实现的接口:Class X implements A, B, C, D。您可以创建捕获组 (?:,\s+([^\s]+))?(匹配零次或一次),并重复它... (?:,\s+([^\s]+))?(?:,\s+([^\s]+))?(?:,\s+([^\s]+))? 现在将匹配多达3个实现的类。在Python中,这甚至更容易,因为您可以像 pattern = '(?:,\s+([^\s]+))?' * 3 这样做等等。 - Decoded

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接