【问题标题】:How to capture multiple sequence of numbers as repeated groups?如何将多个数字序列捕获为重复组?
【发布时间】:2021-09-09 22:11:06
【问题描述】:

我有一个包含多个数字序列的 URL 我想将它们全部分组,假设我有以下内容

https://www.example.com//first/part/54323?key=value

https://www.example.com/first/12345/second/part/part2/5432?key=value

我尝试使用类似的东西,但它只匹配一个数字序列

(.*\/)([0-9]{4,})(\/.*|$|)

如果包含数字序列,我希望多个组代表不同的部分

  • 第一组将是“example.com/first”
  • 第二组“12345”
  • 第三组“第二/部分”
  • 第四组“5432”
  • 第五组“?key=value”

【问题讨论】:

  • 您只想要数字序列还是还想要一些其他文本?
  • 我希望两者实际上都有多个组第一组将是“example.com/first”第二组“12345”第三组“second/part”第四组“5432”第五组“?key=value”

标签: regex regex-greedy


【解决方案1】:

开头的 .* 是 Greedy,这意味着它会尝试尽可能多地匹配。它匹配到最后一个斜杠“https://www.example.com/first/12345/second/part”的所有内容。您可以通过将初始的 .* 替换为 .*? 来修改此行为,但这将在第一个斜杠之后停止,这也不是您想要的“https:/”,因为这些斜杠之后没有数字。

但实际上我们需要备份并询问有关您的模式的一些问题。显然,你有一个你不感兴趣的序言,不定数量的“字符串,后跟斜杠,后跟数字字符串”序列,然后是“没有更多的斜杠数字模式之后的所有内容”。

关键问题是 char/char/digits 组合的数量是不确定的还是限制为一个确定的数字,就像您示例中的两对一样。要让正则表达式解析器返回无限数量的字符串-数字对,您需要打开 /g(全局)开关,以便正则表达式返回所有匹配项。这是您的 URL 开头和结尾部分不符合您的模式的问题。

我建议首先使用正则表达式将您的 URL 分为三个部分,preamble, path, remaining data。然后你可以将路径字符串传递给第二个正则表达式来解析这些对 - 这会简单得多。

如果你这样做,你的第一个表达式可能是:

^[a-z+.-]+?:\/\/(:www\.)?([^?#]+?)(.*)$

第一部分通过可选的 www. 跳过所有内容,并且没有捕获它,因为您对该部分不感兴趣。第二部分捕获所有查询或片段(分别由 ? 和 # 分隔)并将其放置在第一个捕获组中。最后一部分将 URL 的其余部分捕获到第二个捕获组中。在您的示例中是 ?key=value

现在获取包含主机和路径的第一个捕获组,并将其传递给设置了全局标志的第二个正则表达式(因此它重复处理所有对)。第二个正则表达式将是:

(.*?)\/([0-9]{4,})\/?

对于此字符串的每个匹配项,解析的值和数字将位于捕获组 1 和 2 中。

【讨论】:

  • 老实说,我没有这样做的奢侈,因为这个正则表达式是我用于过滤 URL 的工具的模式的一部分,它不是我可以执行多个步骤的完整程序的一部分达到最终结果
【解决方案2】:

听起来很直接:

https?:\/\/(?:www\.)?(.*?)\/(\d+)\/(.*?)\/(\d+)(?:\?(.*))?

regex proof.

解释

--------------------------------------------------------------------------------
  http                     'http'
--------------------------------------------------------------------------------
  s?                       's' (optional (matching the most amount
                           possible))
--------------------------------------------------------------------------------
  :                        ':'
--------------------------------------------------------------------------------
  \/                       '/'
--------------------------------------------------------------------------------
  \/                       '/'
--------------------------------------------------------------------------------
  (?:                      group, but do not capture (optional
                           (matching the most amount possible)):
--------------------------------------------------------------------------------
    www                      'www'
--------------------------------------------------------------------------------
    \.                       '.'
--------------------------------------------------------------------------------
  )?                       end of grouping
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    .*?                      any character except \n (0 or more times
                             (matching the least amount possible))
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  \/                       '/'
--------------------------------------------------------------------------------
  (                        group and capture to \2:
--------------------------------------------------------------------------------
    \d+                      digits (0-9) (1 or more times (matching
                             the most amount possible))
--------------------------------------------------------------------------------
  )                        end of \2
--------------------------------------------------------------------------------
  \/                       '/'
--------------------------------------------------------------------------------
  (                        group and capture to \3:
--------------------------------------------------------------------------------
    .*?                      any character except \n (0 or more times
                             (matching the least amount possible))
--------------------------------------------------------------------------------
  )                        end of \3
--------------------------------------------------------------------------------
  \/                       '/'
--------------------------------------------------------------------------------
  (                        group and capture to \4:
--------------------------------------------------------------------------------
    \d+                      digits (0-9) (1 or more times (matching
                             the most amount possible))
--------------------------------------------------------------------------------
  )                        end of \4
--------------------------------------------------------------------------------
  (?:                      group, but do not capture (optional
                           (matching the most amount possible)):
--------------------------------------------------------------------------------
    \?                       '?'
--------------------------------------------------------------------------------
    (                        group and capture to \5:
--------------------------------------------------------------------------------
      .*                       any character except \n (0 or more
                               times (matching the most amount
                               possible))
--------------------------------------------------------------------------------
    )                        end of \5
--------------------------------------------------------------------------------
  )?                       end of grouping

【讨论】:

  • 这只会匹配我提供的确切模式,如果我们传递的内容包含更多无法匹配的 URL 段,我只是想排除数字序列,所有内容都应该组合在一起跨度>
  • @Mohab 好的,现在看。
猜你喜欢
  • 2016-08-28
  • 2015-07-17
  • 2019-09-25
  • 2015-04-03
  • 2020-06-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-28
相关资源
最近更新 更多