如何强制正则表达式捕获最大匹配?

时间:2016-07-13 19:43:39

标签: regex web regex-greedy

我正在努力防止恶意注入网站。我这样做的方式是创建一个"修剪" URL的任何额外部分都会使其成为非法的。

为了使网址合法,必须遵循以下格式:

  

(任何东西)(几个特定的​​路径前身之一)(特定页面)

例如,假设您的路径前辈是......

  

["服务","服务/城市","特价","特价/限制/"]

一些示例输入和结果:

  

www.fake.com/services/home - > (合法,无修剪) - >   www.fake.com/services/home

     

www.fake.com/services/city/nyc - > (合法,无修剪) - >   www.fake.com/services/city/nyc

     

www.fake.com/services/city/nyc/fakeinjection.txt - > (非法) - >   www.fake.com/services/city/nyc

     

www.fake.com/specials/limited/california/fake/fake/fake.bak - >   (非法) - > www.fake.com/specials/limited/california

所以我编写了以下正则表达式以仅匹配输入URL的合法部分:

/.*(services|services\/city|specials|specials\/limited)\/[^\/]*/gi

问题在于它并不总是捕获最大可能的匹配,因此无意中修剪过多。例如:

www.fake.com/services/city/nyc - > (应该是合法的,不应该修剪) - > www.fake.com/services/city /

我知道为什么会发生这种情况。我相信它正在捕捉它看到的第一件事并与之相匹配。但我需要强迫它采取最大的可能,只在必要时修剪。我认为"贪心" flag会帮助做到这一点,但事实并非如此。

有人可以就解决方案提供一些指导吗?非常感谢。

(PS。如果它有所不同,我使用的语言是javascript)

1 个答案:

答案 0 :(得分:2)

如果你有一个非锚定的交替小组,你应该先放置最长的替代方案。在任何NFA正则表达式中,匹配的第一个分支停止处理交替组并继续使用后续模式。

所以,你可以使用

/.*(services\/city|specials\/limited|services|specials)\/[^\/]*/
    ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^ ^^^^^^^^

请参阅regex demo

如果您使用可选组手动创建模式以减少回溯,则可以进一步增强此列表:

/.*(services(?:\/city)?|specials(?:\/limited))\/[^\/]*/

甚至

/.*(s(?:ervices(?:\/city)?|pecials(?:\/limited)))\/[^\/]*/