以逗号分隔的重复

时间:2011-03-08 15:45:47

标签: regex

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

([abc]+|[123]+)

为条目。为了匹配我逗号分隔的列表,我匹配这样的东西:

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

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

我觉得必须有一个更好的方法,比拥有两个条目副本 - 一次是第一次进入,再次进行并遵循逗号/条目对。

4 个答案:

答案 0 :(得分:7)

看起来你想要 backreferences

([abc123])(,\1)*

<击>

另外,仅供参考,[abc]|[123]相当于[abc123]


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

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

或者如果你想减少限制:

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

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

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

或者你可以用逗号分开:

myString.split(/,/)

答案 1 :(得分:4)

或许这样的事情:

((?!=^|,)([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 (最简单的演示方式)

答案 2 :(得分:1)

我忽略了组捕获挑战并将其视为仅验证问题,即给定的字符串对于我的用例是否是有效的 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

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

答案 3 :(得分:0)

在我的情况下,我正在测试整条线。

/(?!^,)^((^|,)([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);