簡體   English   中英

RegEx驗證以逗號分隔的選項列表

[英]RegEx to validate a comma separated list of options

我正在使用PHP的過濾器功能(特別是FILTER_VALIDATE_REGEXP)來驗證輸入數據。 我有一個選項列表,$ input變量可以從列表中指定多個選項。

選項是(不區分大小寫):

  1. 所有
  2. 獎勵
  3. 加入
  4. 促銷
  5. 報到
  6. verified_checkin

$ input變量可以具有值的幾乎任何組合。 可能的成功案例是:

  • 所有(值可以是all 其他值的逗號分隔的列表但不是兩者)
  • rewards,stream,join (以逗號分隔的值列表, 不包括 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM