匹配独特的群体

时间:2016-04-01 22:07:27

标签: regex

我想将我的产品过滤器放在我的网址中,但要匹配过滤词:

预期比赛:

filter:city:cityname-type:something-type2:something123-price:1000 

filter:city:cityname-type2:something-type:something123-price:1000 

filter:city:cityname-price:1000 

更确切地说: string以“filter:”字开头,之后必须至少有一个过滤器。每个过滤器都是name:value

第一个过滤器(在本例中为“city”)是强制性的,其他则不是,其他人的订单也可以更改(city,type,type2 OR city,type2,type)。预期的过滤器至少为1 - 20.

这是正在使用的正则表达式

^filter:((city:([a-z0-9]+)){1}((-type:([a-z0-9]+))|(-type2:([a-z0-9]+))|(-price:([0-9]+)))*)

如何只匹配每个使用过的过滤器一次,因为上面的正则表达式将匹配:

filter:city:some-price:123-type2:aaa-type2:bbb 

(type2不止一次使用)。如果有更好的正则表达式请发布。

1 个答案:

答案 0 :(得分:1)

您可以使用

^(?!.*[-:](\b(?:city|type2?|price):).*\1)filter:((city:([a-z0-9]+))((-type:([a-z0-9]+))|(-type2:([a-z0-9]+))|(-price:([0-9]+)))*)\s*$

请参阅regex demo

前瞻(?!.*[-:](\b(?:city|type2?|price):).*\1)将检查(在字符串的开头)并且如果字符串包含(内部某处)-:后跟整个单词(如\b是单词边界)city,或type,或type2,或price后跟:(此键被捕获到群组中) 1使用(...))然后使用0+个字符(.*)然后使用相同的捕获键(因为\1是对捕获值的反向引用)。

\s*$将允许尾随空格和字符串结尾,并且将禁止使用未知过滤器。

要缩短模式,请在PCRE / Boost中使用

^(?!.*[-:](\b(?:city|type2?|price):).*\1)filter:(city|type2?|price):([a-z0-9]+)(?:-(?2):(?3))*\s*$

请参阅regex demo(在Ruby中,\g<1>可以使用\g<2>代替(?1)(?2))。

如果正则表达式的风格不同并且不允许递归,请使用

^(?!.*[-:](\b(?:city|type2?|price):).*\1)filter:(?:city|type2?|price):[a-z0-9]+(?:-(?:city|type2?|price):[a-z0-9]+)*$

请参阅another demo