Regex para que coincida con un dígito dos o cuatro veces

96

Es una pregunta simple sobre expresiones regulares, pero no encuentro la respuesta.

Quiero determinar si un número aparece en secuencia exactamente dos o cuatro veces. ¿Qué sintaxis puedo utilizar?

\d{what goes here?}

Lo intenté \d{2,4}, pero esta expresión también acepta tres dígitos.

Renato Dinhani
fuente
1
Por ejemplo, para que coincida con una de dos o cuatro dígitos del año .
DavidRR
¿Qué quieres que suceda si la cadena es abc 123 xyz? ¿Debería coincidir 12porque son exactamente dos dígitos en secuencia? ¿O no debería hacerlo, porque 12es parte de una secuencia de dígitos más grande 123que no tiene ni 2 ni 4 de largo? Si tuviera que adivinar, pensaría que desea este último comportamiento, pero su pregunta no está claro. Los ejemplos y / o una especificación más clara ayudarían. La misma pregunta para abc 12345 def... ¿qué debería pasar allí?
Jean-François Corbett

Respuestas:

148

No hay una sintaxis específica para eso, pero hay muchas formas de hacerlo:

(?:\d{4}|\d{2})    <-- alternation: four digits or two
\d{2}(?:\d{2})?    <-- two digits, and optionally two more
(?:\d{2}){1,2}     <-- two digits, times one or two
ruakh
fuente
1
Personalmente, solo pensé en la \d{2}(?:\d{2})?solución desde el principio, una buena variedad de estas, la última, en particular, parecía muy agradable y escalable.
Nightfirecat
3
+1 por tener en cuenta el orden necesario cuando se usa la alternancia para hacer coincidir 4 dígitos primero y luego 2 dígitos. También buen trabajo proporcionando las otras variaciones.
Ahmad Mageed
9
Para cualquiera que, como yo, no entendiera el uso de (?:esto, comienza un "grupo de no captura" (un grupo que no está destinado a ser referenciado en una declaración de reemplazo). También puede usar parens, pero estos crearán un grupo de captura. Más detalles aquí: stackoverflow.com/questions/3512471/non-capturing-group
Jeremy Moritz
Estos mostrarán el mismo resultado para "333" y "33"
Dan
1
@Dan: estas expresiones regulares no coinciden con la cadena completa "333". Es posible que esté utilizando la funcionalidad "buscar subcadena coincidente" de su biblioteca de expresiones regulares por error, en lugar de su funcionalidad "verificar si la cadena completa coincide". Debes consultar su documentación.
ruakh
3
(?<!\d)(\d{2}|\d{4})(?!\d)

Esta es la forma correcta de hacerlo. La respuesta aceptada es incorrecta.

Coincidiría con 3 dígitos (o 5). Entonces eso está mal en mis ojos .

1) Compruebe que no haya ningún dígito antes de una secuencia de 2 o 4 dígitos, o después de una secuencia de dos o cuatro dígitos.

  • (<!) la sintaxis es retroceso negativo

  • (?!) la sintaxis es una búsqueda anticipada negativa.

Lo anterior funcionaría para la cuerda media:

Si la cadena de búsqueda no tiene contenido alrededor de él se podría utilizar el ^e $iniciar y terminar de anclajes de cadena:

^\d{4}$|^\d{2}$
JGFMK
fuente
1
No diría que la respuesta aceptada es incorrecta. Yo diría que la pregunta no está clara y que esa respuesta aborda una interpretación válida de la misma. Su respuesta aborda otra interpretación válida (que creo que es más probable, pero aparentemente el autor de la pregunta no lo hizo ...).
Jean-François Corbett
2
"Coincidiría con 3 dígitos" no es del todo exacto. Creo que quiere decir "Coincidiría con una subsecuencia de 2 dígitos de una secuencia de 3 dígitos".
Jean-François Corbett
1
Además, su respuesta no funciona como se esperaba en secuencias de 5 o más dígitos . No soy un experto en expresiones regulares, pero supongo que una forma de solucionarlo es hacer que la búsqueda hacia adelante / atrás negativa se aplique a ambos casos (secuencias de 2 y 4 dígitos):(?<!\d)(\d{2}|\d{4})(?!\d)
Jean-François Corbett
Creo que tienes razón sobre los 5 dígitos. Gracias por esa corrección. Lo arreglaré.
JGFMK
^\d{4}$|^\d{2}$sería una forma potencial de solucionarlo. Como lo haría^\d{2}(?!\d)|^\d{4}(?!\d)
JGFMK