在正则表达式中捕获组

时间:2019-06-19 17:44:58

标签: regex nginx

我有字符串a/b/c/,我想通过正则表达式获得3个组(a/b/c/)。

所以,我可以做到

^([^\/]+\/)([^\/]+\/)([^\/]+\/)$

但是它不是很优雅。 我想做这样的事情

^([^\/]+\/){3}$

但我得到警告:

A repeated capturing group will only capture the last iteration. Put a capturing group around the repeated group to capture all iterations or use a non-capturing group instead if you're not interested in the data

所以,我对数据感兴趣,但是我不明白我应该在正则表达式中进行哪些更改才能获得有效的结果。

Test on regex101

上下文的小示例(nginx配置):

location ~* ^/([^/]+/)([^/]+/)([^/]+/)$ {
  rewrite (?i)^/([^/]+/)([^/]+/)([^/]+/)$ /$3$2$1 break;
}

在这种情况下,我将网址从/a/b/c/重写为/c/b/a/

2 个答案:

答案 0 :(得分:0)

实际上,您没有什么办法可以减少重复:

^([^\/]+\/)([^\/]+\/)([^\/]+\/)$

警告告诉您,诸如([^\/]+\/){3}之类的重复组仅会捕获最后一个重复。您可能会认为([^\/]+\/){3}是3个组,但是它只有一个组,因为只有一对括号。该组将包含量词匹配的最后一项内容,在这种情况下为c/

要有3组,必须有3对括号。

如果您真的要缩短正则表达式,可以尝试:

[^\/]+\/

这将创建3个 matches 而不是组,但是您必须使用代码检查以下内容:

  • 一共有三场比赛
  • 每场比赛的结束都是下一场比赛的开始
  • 第一个匹配项从字符串的开头开始
  • 最后一个匹配项结束于字符串的结尾

以达到与原始正则表达式相同的效果。

答案 1 :(得分:0)

模式^([^\/]+\/){3}$将组重复3次,但组1仅包含上次迭代的值。在给定组的返回值是最后一个被捕获的中,this page可能会有所帮助。

如果要分组1、2和3,则必须在模式中使用3个捕获组。

不确定这是否更优雅,但也许可以选择使用\G获得3个单独的比赛来获得迭代比赛,并使用正向提前(?=来断言不是前锋的模式斜杠后跟/出现3次:

(?:(?=^(?:[^/]+/){3}$)|\G(?!^))[^/]+/
  • (?:非捕获组
    • (?=正向前进,断言右边是
      • ^(?:[^/]+/){3}$匹配3次不是正斜杠,然后是/
    • )积极回望
    • |
    • \G(?!^)在上一场比赛的末尾(而不是在开始时)断言位置
  • )关闭非捕获组
  • [^/]+/不匹配正斜杠,然后匹配/

查看regex demo