2011-03-08 18 views
9

Tengo una expresión regular bastante larga para que coincida con una entrada en una lista que estoy procesando. La lista debe ser una o más de estas entradas, separadas por comas. Considere una expresión regular:Repeticiones separadas por comas

([abc]+|[123]+) 

para la entrada. Para que coincida con mi lista separada por comas, que estoy a juego en contra de algo como esto:

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

(se ve especialmente tonta con mi desagradable expresión regular en lugar de la corta que se utiliza aquí para el ejemplo)

I Siente que debe haber una mejor manera que tener dos copias de la entrada, una para la primera entrada, nuevamente para y seguir los pares de coma/entrada.

Respuesta

3

Algo como esto quizá:

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

se rompió es:

(      # 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 (¿Era más simple manera de demostrar)

+0

No creo que quiera el '!' En su mirada hacia adelante (que es para una mirada negativa), pero una mirada hacia adelante no coincide con un personaje, por lo que no coincidirá. Que debe estar bien sin lookahead '|' + – jswolf19

+0

@ jswolf19 (:: (^,) ([a-C1-3])??): Yo uso para evitar que el carácter de liquidación en el partido. Supongo que preferencia personal. - La combinación también me da el primer partido y el resto. (sin él, obtendré solo el primer token, o el 2do en adelante) –

+0

Sé que no quieres el ',' en el partido, pero tiene que coincidir: si tienes 'a, 1', entonces tu expresión regular no coincidirá. el buscador anticipa el ',', pero aún está allí cuando tratas de unir el 1 porque el futuro no tira el ',' lejos. Necesitas un grupo que no capture para eso '(?:)'. – jswolf19

6

Parece que desea backreferences.

([abc123])(,\1)* 

Además, sólo FYI, [abc]|[123] es equivalente a [abc123].


Editar: Sobre la base de su edición, creo que no he entendido bien lo que estaba tratando de hacer. Prueba esto:

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

O si quieres ser menos restrictiva:

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

Esto coincide con las cadenas de caracteres no comas separadas por comas. Un enfoque más simple sería una coincidencia global para [^,]+ por sí mismo. En JavaScript, que se vería así:

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

O simplemente puede dividir en comas:

myString.split(/,/) 
+0

que va a decir que el próximo token tiene que ser el mismo que el anterior, no que deba ajustarse al patrón. (No estoy seguro de que eso es lo que quiere el OP, solo tienen curiosidad si necesitan especificar el patrón dos veces [podría estar equivocado ...]) –

+0

@radio: ¿No es eso lo que él está buscando? Tal vez estoy confundido. –

+0

@JustinEMorgan: Quizás tengas razón. Lo leí como "¿necesito especificar el patrón para buscar dos veces?" Y "de lo contrario, cómo evitarlo". –

0

En mi caso estoy probando toda la línea.

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

La anticipación negativa excluye una coma inicial.

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

Si necesita los componentes individuales, haga una simple división después de la validación.

Estoy validando las secciones y subsecciones de subdivisión 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}))+$ 

Una vez validado, me he separado usando un aspecto positivo detrás.

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