【问题标题】:Capture section of a repeating regex capture group重复正则表达式捕获组的捕获部分
【发布时间】:2016-03-03 12:41:39
【问题描述】:
^([a-z-]+-on-sale(?:,[a-z-]+-on-sale){0,})[\/]$

这个正则表达式用在一个 htaccess 文件中并匹配一个模式,比如这个:

tools-on-sale,candy-on-sale,food-on-sale/

我一直想知道我是否有可能捕获重复捕获组的一部分。我想匹配相同的模式,但我想省略重复捕获组中的“-on-sale”部分。我知道我已经可以为正则表达式的第一部分做到这一点:

^(([a-z-]+)-on-sale(?:,[a-z-]+-on-sale){0,})[\/]$

这样我在自己的捕获组中隔离了“工具”,但我似乎无法对第二部分进行同样的操作。这甚至可以使用正则表达式吗?

【问题讨论】:

    标签: regex .htaccess


    【解决方案1】:

    没有捷径可以实现这一目标。但是,您可以定义您应该期望的最大项目数,并为每个项目创建一个可选组。

    对于 1 到 3 项:

    ^([a-z-]+)-on-sale(?:(,[a-z-]+)-on-sale(?:(,[a-z-]+)-on-sale)?)?/$
    

    请求网址

    http://foo.bar/tools-on-sale,candy-on-sale,food-on-sale/
    

    htaccess

    RewriteRule ^([a-z-]+)-on-sale(?:(,[a-z-]+)-on-sale(?:(,[a-z-]+)-on-sale)?)?/$ http://foo.bar/$1$2$3 [L]
    

    *感谢 @sln 提出改进建议

    输出网址

    http://foo.bar/tools,candy,food
    

    但是,如果您需要逗号以外的分隔符,如果您的项目少于 3 个,则会生成空标记。例如:

    http://foo.bar/tools--
    

    如果必须避免,则需要为每个项目数创建 1 条规则:

    RewriteRule ^([a-z-]+)-on-sale,([a-z-]+)-on-sale,([a-z-]+)-on-sale/$ http://foo.bar/$1-$2-$3 [L]
    RewriteRule ^([a-z-]+)-on-sale,([a-z-]+)-on-sale/$ http://foo.bar/$1-$2 [L]
    RewriteRule ^([a-z-]+)-on-sale/$ http://foo.bar/$1 [L]
    

    【讨论】:

    • 你可能会使用一个正则表达式而不是通过将逗号放在捕获组RewriteRule ^([a-z-]+)-on-sale(?:(,[a-z-]+)-on-sale(?:(,[a-z-]+)-on-sale)?)?/$ http://foo.bar/$1$2$3 [L]中来获取空标记@
    • @sln 不错!我没看到。谢谢。
    【解决方案2】:

    如果我想我理解你,你想得到一份特价的清单吗?

    您已经知道如何捕获第一个工具
    但是,您需要在单场比赛中使用它。

    好消息是只有 Dot-Net 可以在捕获集合中执行此操作,
    像这样:

     # ^((?:(?:^|(?<!^),)(?<sale_item>[a-z-]+)-on-sale)+)[\/]$
    
     ^     
     (                             # (1 start)
          (?:
               (?:
                    ^ 
                 |  (?<! ^ )
                    , 
               )
               (?<sale_item> [a-z-]+ )       # (2)
               -on-sale 
          )+
     )                             # (1 end)
     [\/] $
    

    sale_item 是一个列表。

    坏消息是,在所有其他正则表达式引擎上,
    整体匹配将是相同的,但 sale_item 捕获缓冲区
    被量化组的每次迭代覆盖。
    因此,sale_item 将仅包含 last 项“食物”。

    【讨论】:

    • 不确定我是否理解,不,我使用的是 Apache 和 PHP,而不是 Dot-Net。 “on-sale”(实际上不是它,它是一个例子)部分最初是为了“帮助 SEO”而添加的,我正试图完全摆脱“-on-sale”部分来做一个301 重定向到不包含“-on-sale”的新 URL。问题是目前,我正在捕获它并且我不想要它。我仍然想匹配它,但我希望能够在没有它的情况下进行捕捉。否则我会在 PHP 中处理 URL,并手动执行 301 重定向。
    • @Sefam - I'm capturing it and I don't want it. I still want to match it, but I want to be able to capture without it 你已经回答了你自己的问题。问题是您正在使用量化组来匹配连续出现的事件。捕获组是单一的。如果我在hellohellohello 上使用(hello)+,我不会得到['hello','hello','hello'],我会得到['hello']。您只能使用 Dot-Net 进行聚合。否则,您必须在有限表达式中创建一个唯一组。请参阅@Mariano 的答案。
    猜你喜欢
    • 2017-09-13
    • 2011-03-11
    • 2017-01-07
    • 2019-12-19
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多