有时正则表达式只会使事情变得比应有的复杂。正则表达式非常擅长匹配模式,但是当您引入依赖于匹配模式数量的外部规则时,事情会很快变得复杂。
在这种情况下,我只需用逗号拆分列表,并根据您刚刚描述的规则检查生成的字符串。
$valid_choices = array('checkin','join','promotions','rewards','stream','verified_checkin');
$input_string; // string to match
$tokens = explode(',' $input_string);
$tokens = asort($tokens); // sort to tokens to make it easy to find duplicates
if($tokens[0] == 'all' && count($tokens) > 1)
return FALSE; // fail (all + other options)
if(!in_array($tokens[0], $valid_choices))
return FALSE; // fail (invalid first choice)
for($i = 1; $i < count($tokens); $i++)
{
if($tokens[$i] == $tokens[$i-1])
return FALSE; // fail (duplicates)
if(!in_array($tokens[$i], $valid_choices))
return FALSE; // fail (choice not valid)
}
编辑
既然你编辑了你的并指定重复是可以接受的,但你肯定想要一个基于正则表达式的解决方案,那么这个应该这样做:
^(all|((checkin|verified_checkin|rewards|join|promotions|stream)(,(checkin|verified_checkin|rewards|join|promotion|stream))*))$
它不会因重复而失败,但它会小心或前导或尾随逗号,或所有+其他选择组合。
使用正则表达式过滤掉重复项非常困难,但也许并非不可能(如果您使用带有捕获组占位符的前瞻)
第二次编辑
虽然您提到检测重复条目并不重要,但我想我会尝试制作一个也可以检查重复条目的模式。
正如您在下面看到的那样,它不是很优雅,也不容易扩展,但它确实可以通过使用负前瞻的有限选项列表完成工作。
^(all|(checkin|verified_checkin|rewards|join|promotions|stream)(,(?!\2)(checkin|verified_checkin|rewards|join|promotions|stream))?(,(?!\2)(?!\4)(checkin|verified_checkin|rewards|join|promotions|stream))?(,(?!\2)(?!\4)(?!\6)(checkin|verified_checkin|rewards|join|promotions|stream))?(,(?!\2)(?!\4)(?!\6)(?!\8)(checkin|verified_checkin|rewards|join|promotions|stream))?(,(?!\2)(?!\4)(?!\6)(?!\8)(?!\10)(checkin|verified_checkin|rewards|join|promotions|stream))?)$
由于最终的正则表达式很长,我将把它分成几部分,以便更容易理解总体思路:
^(all|
(checkin|verified_checkin|rewards|join|promotions|stream)
(,(?!\2)(checkin|verified_checkin|rewards|join|promotions|stream))?
(,(?!\2)(?!\4)(checkin|verified_checkin|rewards|join|promotions|stream))?
(,(?!\2)(?!\4)(?!\6)(checkin|verified_checkin|rewards|join|promotions|stream))?
(,(?!\2)(?!\4)(?!\6)(?!\8)(checkin|verified_checkin|rewards|join|promotions|stream))?
(,(?!\2)(?!\4)(?!\6)(?!\8)(?!\10)(checkin|verified_checkin|rewards|join|promotions|stream))?
)$/
您可以看到形成模式的机制有些迭代,如果您想提供不同的列表,算法可以自动生成这样的模式,但生成的模式会变得相当大,相当快。