[英]RegEx to validate a comma separated list of options
我正在使用PHP的過濾器功能(特別是FILTER_VALIDATE_REGEXP)來驗證輸入數據。 我有一個選項列表,$ input變量可以從列表中指定多個選項。
選項是(不區分大小寫):
$ input變量可以具有值的幾乎任何組合。 可能的成功案例是:
all
或其他值的逗號分隔的列表但不是兩者) all
) 我已經想出的正則表達式是:
/^(?:all|(?:checkin|verified_checkin|rewards|join|promotions|stream)?(?:,(?:checkin|verified_checkin|rewards|join|promotion|stream))*)$/
到目前為止,它適用於以下示例方案:
all
(通過) rewards,join,promotion,checkin,verified_checkin
(通過) join
(通過) 但是,它讓值以逗號開頭,並通過以下方式重復:
,promotion,checkin,verified_checkin
(以逗號開頭,但在不應該通過時也通過) 此外,檢查重復項將是一個獎勵,但並非必需。
rewards,join,promotion,checkin,join,verified_checkin
(重復的值,但仍然通過,但不如逗號開頭那么關鍵) 我已經使用了幾天,並嘗試了各種實現,這是我能夠獲得的最接近的實現。
關於如何處理前導逗號誤報的任何想法?
更新:編輯了問題,以更好地解釋重復過濾並不是真正的要求,而只是獎金。
有時,正則表達式會使事情變得比原本應該的復雜。 正則表達式確實擅長於匹配模式,但是當您引入依賴於匹配模式數量的外部規則時,事情就會變得很復雜。
在這種情況下,我只用逗號分割列表,然后根據您剛剛描述的規則檢查結果字符串。
$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))?
)$/
您可以看到,形成模式的機制在某種程度上是迭代的,如果您想提供其他列表,則算法可以自動生成這種模式,但是生成的模式會變得相當大,而且很快。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.