Regex 带贪婪量词的正则表达式前瞻问题

Regex 带贪婪量词的正则表达式前瞻问题,regex,greedy,lookahead,quantifiers,Regex,Greedy,Lookahead,Quantifiers,需要支持以下格式 3位数字,后跟可选空格,后跟以下字符集ACERV中指定的三个非重复字符(空格仅在两个字符之间有效) 有效格式: 123 123 A 123 A v 123 CER 123A 123 AA 123 A - when followed by a space 无效格式: 123 123 A 123 A v 123 CER 123A 123 AA 123 A - when followed by a space 到目前为止,我所拥有的——我可能会将这一点过于复杂化,因为不一

需要支持以下格式

3位数字,后跟可选空格,后跟以下字符集ACERV中指定的三个非重复字符(空格仅在两个字符之间有效)

有效格式:

123
123 A
123 A v
123 CER
123A
123 AA
123 A  - when followed by a space
无效格式:

123
123 A
123 A v
123 CER
123A
123 AA
123 A  - when followed by a space
到目前为止,我所拥有的——我可能会将这一点过于复杂化,因为不一定需要这些外观:

^([0-9]{3})                                         # - first 3 digits
 (\s(?=[ACERV]))([ACERV])                           # - allow space only when followed by ACERV
 (?!\3)(?=[ACERV ]{0,1})([ACERV ]{0,1})             # - do not allow 1st char to repeat
 (?!\3)                                             # - do not allow 1st char to repeat
 (?!\4)                                             # - do not allow 2nd to repeat
 (?!\s)                                             # - do not allow trailing space
 (?=[ACERV]{0,1})([ACERV]{0,1})|[0-9]{3}$
添加前瞻(?!\4)时,它在有效格式123 A上无法匹配-将(?!\4)上的量词修改为(?!\4)*或(?!\4)?允许123 A匹配,但允许重复第一个或第二个字符。

正则表达式如何

^\d{3}(?:$|\s)(?:([ACERV])(?!\1)|\s(?!$|\1))*$
将匹配字符串

123
123 A
123 A V
123 CER
看看正则表达式是如何计算的

  • ^
    将正则表达式锚定在字符串的开头

  • \d{3}
    匹配任何数字的3次出现

  • (?:$\s)
    匹配字符串的结尾
    $
    或空格,
    \s

  • (?:\s)([ACERV])(?!\1)){0,3}
    匹配
    [ACERV]

    • (?:)
      非捕获组

    • \s?
      可选空格

    • ([ACERV])
      匹配类中的字符

    • (?:([ACERV])(?!\1)|\s(?!$\1))
      断言正则表达式后面没有最近捕获的字符
      \1
      。确保字符不重复

      • (?!\1)
        声明字符类后面不能有重复字符

      • \s(?!$\1))
        断言,如果它是一个空格,则后面不能跟有
        \1

    • {0,3}
      指定最小发生次数为零、最大发生次数为3的量词

  • $
    将正则表达式锚定在字符串的末尾


    • 不完全确定要求,这适用于您的样品

       # ^(?i)\d{3}(?:[ ](?:([ACERV])[ ]?(?![ACERV ]*\1)){1,3}(?<![ ]))?$
      
       ^                      # BOL
       (?i)                   # Case insensitive modifier
       \d{3}                  # 3 digits
       (?:                    # Cluster grp, character block (optional)
            [ ]                    # Space, required
            (?:                    # Cluster grp
                 ( [ACERV] )            # (1), Capture single character [ACERV]
                 [ ]?                   # [ ], optional
                 (?!                    # Negative lookahead
                      [ACERV ]*              # As many [ACERV] or [ ] needed
                      \1                     # to find what is captured in group 1
                                             # Found it, the assertion fails
                 )                      # End Negative lookahead
            ){1,3}                 # End Cluster grp, gets 1-3 [ACERV] characters
            (?<! [ ] )             # No dangling [ ] at end
       )?                     # End Cluster grp, character block (optional)
       $                      # EOL  
      

      一个计划是使用简单的regexp分离字符串,然后第二步验证字符是否重复

      // check all characters in a string are unique,
      // by ensuring that each character is its own first appearance
      function unique_characters(str) {
          return str.split('').every(function(chr, i, chrs) {
              return chrs.indexOf(chr) === i;
          });
      }
      
      // check that the code is valid
      function valid_code(str) {
          var spacepos = str.indexOf(' ');
          return unique_characters(str) &&
              (spacepos === -1 || (spacepos === 1 && str.length === 3));
      }
      
      // check basic format and pull out code portion
      function check_string(str) {
          var matches = str.match(/^\d{3} ?([ACERV ]{0,3})$/i);
          valid = matches && valid_code(matches[1]);
          return valid;
      }
      
      >> inputs = ['123', '123 A', '123 A v', '123 CER', '123A', '123 AA', '123 A ']
      [true, true, true, true, true, false, false]
      
      第四个测试用例显示为有效,因为如果空格确实是可选的,那么如果
      123A
      是有效的,那么
      123A
      似乎也是有效的


      这种方法的一个可能的优点是,如果引入了额外的验证规则,它们可以比在一个巨大的regexp中乱动更容易实现。

      为什么123在文本字段中是无效的?非重复的相邻或任何位置?非重复的仅限格式(即,只允许单个输入123 AEV)这需要纯regexp吗?我不明白你的规则。你说空格是可选的,但“123A”是有效的,而“123A”是无效的?不确定你所说的#符合你的定义是什么意思。。。在最初的问题中,我可能没有很好地说明这一点。数字后跟可选字符时需要空格。所以123A不应该匹配。@DavidBrown在回答中更正。希望它现在匹配良好现在它不匹配123 A Vignore之前的评论它似乎允许任何数量的空格(即123\b\b\bA或123\b\b\bA\b\b\b\bV)-应该只允许一个空格这看起来很有希望尝试所有变体,然后标记为回答任何可能的评论以下部分:(?!(?:[ACERV](?@DavidBrown-删除了一个不必要的断言,添加了注释。我是否有可能让正则表达式在客户端进行验证。我在csharp中进行测试,现在当添加到客户端时,javascript函数RegularExpressionValidatoreEvaluateIsValid中出现了错误。看起来后面的负面外观导致了问题。