【问题标题】:Comma-separated repeats逗号分隔的重复
【发布时间】:2011-03-08 15:45:47
【问题描述】:

我有一个很长的正则表达式来匹配我正在处理的列表中的条目。该列表应该是这些条目中的一个或多个,以逗号分隔。考虑一个正则表达式:

([abc]+|[123]+)

为条目。为了匹配我的逗号分隔列表,我正在匹配这样的内容:

([abc]+|[123]+)(,([abc]+|[123]+))*

(我讨厌的正则表达式看起来特别愚蠢,而不是我在这里用于示例的简短表达式)

我觉得肯定有比拥有两个条目的副本更好的方法 - 一次用于第一个条目,再次用于逗号/条目对。

【问题讨论】:

    标签: regex


    【解决方案1】:

    看起来你想要backreferences

    ([abc123])(,\1)*
    

    另外,仅供参考,[abc]|[123] 等同于 [abc123]


    编辑:根据您的编辑,我想我误解了您的意图。试试这个:

    ([abc123]+(,|$))*
    

    或者,如果您想减少限制:

    ([^,]+(,|$))*
    

    这匹配由逗号分隔的非逗号字符的字符串。一个更简单的方法就是对 [^,]+ 本身进行全局匹配。在 JavaScript 中,它看起来像这样:

    myString.match(/[^,]+/g) //or /[abc123]+/g, or whatever
    

    或者你可以用逗号分开:

    myString.split(/,/)
    

    【讨论】:

    • 这意味着下一个标记必须与前一个标记相同,而不是它必须符合模式。 (不确定这就是OP想要的,他们只是好奇他们是否需要两次指定模式[我可能错了......])
    • @Brad:这不是他想要的吗?也许我很困惑。
    • @JustinEMorgan:也许你是对的。我将其读作“我是否需要指定要查找两次的模式?”和“如果不需要,我该如何避免这样做”。
    • 我编辑了我的问题。我真的只是在寻找一种将模式扩展到以逗号分隔的自身列表的方法。
    【解决方案2】:

    可能是这样的:

    ((?!=^|,)([abc123]))+
    

    分解它是:

    (                       # start of parent capture
      (?!=^|,)                # look ahead and find either the start of a line or a comma
      ([abc123])              # actual pattern to look for (token)
    )+                      # say this whole pattern is repeatable
    

    PHP Demo(是最简单的演示方式)

    【讨论】:

    • 我认为你不希望在你的前瞻中使用!(这是一个消极的前瞻),但前瞻实际上并不匹配一个字符,所以这不会匹配。没有前瞻应该没问题(?:(?:^|,)([a-c1-3]))+
    • @jswolf19:我用它来避免角色在比赛中结束。我猜个人喜好。 -- 这个组合也给了我第一场比赛和剩下的比赛。 (没有它我要么只得到第一个令牌,要么得到第二个)
    • 我知道你不希望匹配中的 ',',但它必须匹配:如果你有 'a,1',那么你的正则表达式不会匹配它。前瞻会看到“,”,但是当您尝试匹配 1 时它仍然存在,因为前瞻不会将“,”扔掉。您需要为该(?: ) 设置一个非捕获组。
    • @jswolf:不确定what you mean?你的方法只给了我最后一场比赛。 (在您的示例中,行首将首先匹配,然后逗号计入下一个匹配项)
    • 去掉全局标志,你的doesn't match整个字符串就是我的意思。不过,漂亮的网站。
    【解决方案3】:

    我忽略了捕获组的挑战并将其仅视为一个验证问题,即给定的字符串对于我的用例是否是有效的 CSV

    最简单的答案是

    /((^|,)([abc]+|[123]+))+/
    

    然而,这允许一些可能不受欢迎的情况

    ,ab,31,ca         # leading comma
    ab,31,ca,         # trailing comma
    xy,ab,31,ca,76    # leading or trailing invalid values
    

    要解决这些情况,您可以使用

    ^((^(?!,)|(?!^),)([abc]+|[123]+))+$
    
    ^                     # don't allow leading invalid values
    ((
      ^(?!,)              # beginning, not starting with a comma
    |                     # OR
      (?!^),              # not beginning, need a comma             
    )(                    # followed by
      [abc]+|[123]+       # pattern for your valid values
    ))+                   # one or more times
    $                     # don't allow trailing invalid values
    

    这确保没有前导或尾随逗号,并且匹配整行。

    【讨论】:

      【解决方案4】:

      就我而言,我正在测试整行。

      /(?!^,)^((^|,)([abc]+|[123]+))+$/.test('a,b,c,1,2,3');
      true
      

      否定前瞻不包括初始逗号。

      /(?!^,)^((^|,)([abc]+|[123]+))+$/.test(',a,b,c,1,2,3');
      false
      

      如果您需要单个组件在验证后进行简单拆分。

      我正在验证 PLSS 细分部分和子部分。

      // Check for one or more Section Specs consisting of an optional
      // subsection followed by an "S" and one or two digits. Multiple
      // Section Specs are separated by space or a comma and optional space.
      //
      // Example: SW/4 SW/4 S1, E/2 S2, N/2 N/2 S12
      //
      // Valid subsections are -
      //  (1) [NS][EW]/4\s+[NS][EW]/4   eg. NW/4 SE/4 (40 ac)
      //  (2) [NSEW]/2\s+[NS][EW]/4     eg. N/2 SE/4 (80 ac)
      //  (3) [NS]/2\s+[NS]/2           eg. N/2 S/2 (160 ac)
      //  (4) [EW]/2\s+[EW]/2           eg. E/2 W/2 (160 ac)
      //  (5) [NS][EW]/4                eg. NE/4 (160 ac)
      //  (6) [NSEW]/2                  eg. E/2 (320 ac)
      //  (7) 1/1                       Shorthand for the full section (640 ac)
      //
      // Expressions like E/2 N/2 are not valid. Use NE/4 instead.
      // Expressions like NW/4 E/2 are not valid. You probably want W/2 NE/4.
      
      var pat = '' +
          '(([NS][EW]/4|[NSEW]/2)\\s+)?[NS][EW]/4\\s+' +    // (1), (2) & (5)
          '|([NS]/2\\s+)?[NS]/2\\s+' +                      // (3) & part of (6)
          '|([EW]/2\\s+)?[EW]/2\\s+' +                      // (4) & part of (6)
          '|1/1\\s+';                                       // (7)
      
      pat = '(' + pat + ')?' + 'S\\d{1,2}';                 // a Section Spec
      
      // Line anchors, join alternatives and negative lookahead to exclude an initial comma
      pat = '(?!^,)^((^|,\\s*|\\s+)(' + pat + '))+$';
      
      var re = new RegExp(pat, 'i');
      
      console.log(pat);
      (?!^,)^((^|,\s*|\s+)(((([NS][EW]/4|[NSEW]/2)\s+)?[NS][EW]/4\s+|([NS]/2\s+)?[NS]/2\s+|([EW]/2\s+)?[EW]/2\s+|1/1\s+)?S\d{1,2}))+$
      

      验证后,我使用积极的后向分析进行拆分。

      var secs = val.split(/(?<=S\d+)(,\s*|\s+)/i);
      

      【讨论】:

        猜你喜欢
        • 2011-07-26
        • 1970-01-01
        • 2013-07-05
        • 1970-01-01
        • 2017-07-04
        • 2013-10-05
        • 1970-01-01
        • 2012-02-21
        • 2018-12-06
        相关资源
        最近更新 更多