javascript - regulares - Regex para que coincida exactamente con 5 números y un espacio opcional
matches java ejemplo (7)
Recientemente necesité crear una expresión regular para verificar la entrada en JavaScript. La entrada puede tener 5 o 6 caracteres y debe contener exactamente 5 números y un espacio opcional, que podría estar en cualquier lugar de la cadena. No soy conocedor de regex en absoluto y aunque traté de buscar una mejor manera, terminé con esto:
(^/d{5}$)|(^ /d{5}$)|(^/d{5} $)|(^/d{1} /d{4}$)|(^/d{2} /d{3}$)|(^/d{3} /d{2}$)|(^/d{4} /d{1}$)
Esto hace lo que necesito, por lo que las entradas permitidas son (si 0 es cualquier número)
''00000''
'' 00000''
''0 0000''
''00 000''
''000 00''
''0000 0''
''00000 ''
Dudo que esta sea la única forma de lograr ese emparejamiento con expresiones regulares, pero no he encontrado la forma de hacerlo de una manera más limpia. Entonces mi pregunta es, ¿cómo se puede escribir mejor?
Gracias.
Editar:
Entonces, ¡es posible! La respuesta de Tom Lord hace lo que necesitaba con expresiones regulares, así que lo marqué como una respuesta correcta a mi pregunta.
Sin embargo, poco después de publicar esta pregunta, me di cuenta de que no estaba pensando bien, ya que cualquier otra entrada en el proyecto era fácilmente ''validable'' con expresiones regulares, estaba asumiendo inmediatamente que podía validar esta también con ella.
Resulta que podría hacer esto:
const validate = function(value) {
const v = value.replace(//s/g, '''')
const regex = new RegExp(''^//d{5}$'');
return regex.test(v);
}
¡Gracias a todos por las respuestas e ideas geniales! :)
Edit2: Olvidé mencionar un detalle posiblemente muy importante, que es que la entrada es limitada, por lo que el usuario solo puede ingresar hasta 6 caracteres. Mis disculpas.
Aquí hay una expresión regular simple para hacer el trabajo:
^(?=[/d ]{5,6}$)/d*/s?/d*$
Explicación:
^ afirma la posición al inicio de la cadena
Positive Lookahead (? = [/ D] {5,6} $)
Asegúrate de que la Regex a continuación coincide
Haga coincidir un solo carácter presente en la lista siguiente [/ d] {5,6}
{5,6} Cuantificador: coincide entre 5 y 6 veces, tantas veces como sea posible, devolviéndolo según sea necesario (codicioso)
/ d coincide con un dígito (igual a [0-9]) coincide literalmente con el carácter (distingue entre mayúsculas y minúsculas)
$ afirma la posición al final de la cadena / d * coincide con un dígito (igual a [0-9])
- Cuantificador: coincide entre cero y tiempos ilimitados, tantas veces como sea posible, devolviéndolo según sea necesario (codicioso)
/ s coincide con cualquier carácter de espacio en blanco (igual a [/ r / n / t / f / v])
/ d * coincide con un dígito (igual a [0-9])
- Cuantificador: coincide entre cero y tiempos ilimitados, tantas veces como sea posible, devolviéndolo según sea necesario (codicioso)
$ afirma la posición al final de la cadena
Esto me parece más intuitivo y es O (n)
function isInputValid(input) {
const length = input.length;
if (length != 5 && length != 6) {
return false;
}
let spaceSeen = false;
let digitsSeen = 0;
for (let character of input) {
if (character === '' '') {
if (spaceSeen) {
return false;
}
spaceSeen = true;
}
else if (/^/d$/.test(character)) {
digitsSeen++;
}
else {
return false;
}
}
return digitsSeen == 5;
}
Le sugiero que primero compruebe exactamente cinco números ^/d{5}$
O busque un espacio entre números ^(?=/d* /d*$)
entre seis caracteres .{6}$
.
La combinación de esas expresiones parciales genera ^/d{5}$|^(?=/d* /d*$).{6}$
:
let regex = /^/d{5}$|^(?=/d* /d*$).{6}$/;
console.log(regex.test(''00000'')); // true
console.log(regex.test('' 00000'')); // true
console.log(regex.test(''00000 '')); // true
console.log(regex.test(''00 000'')); // true
console.log(regex.test('' 00000'')); // false
console.log(regex.test(''00000 '')); // false
console.log(regex.test(''00 000'')); // false
console.log(regex.test(''00 0 00'')); // false
console.log(regex.test(''000 000'')); // false
console.log(regex.test(''0000'')); // false
console.log(regex.test(''000000'')); // false
console.log(regex.test(''000 0'')); // false
console.log(regex.test(''000 0x'')); // false
console.log(regex.test(''0000x0'')); // false
console.log(regex.test(''x00000'')); // false
Alternativamente, haga coincidir las expresiones parciales por separado, por ejemplo:
/^/d{5}$/.test(input) || input.length == 6 && /^/d* /d*$/.test(input)
Puedes dividirlo a la mitad:
var input = ''0000 '';
if(/^[^ ]* [^ ]*$/.test(input) && /^/d{5,6}$/.test(input.replace(/ /, '''')))
console.log(''Match'');
string="12345 ";
if(string.length<=6 && string.replace(//s/g, '''').length<=5 && parseInt(string,10)){
alert("valid");
}
Simplemente puede verificar la longitud y si es un número válido ...
Nota: Usar una expresión regular para resolver este problema podría no ser la mejor respuesta. Como se explica a continuación , ¡puede ser más fácil simplemente contar los dígitos y espacios con una función simple!
Sin embargo, como la pregunta era una respuesta regular, y en algunos casos puede verse obligado a resolver esto con una expresión regular (por ejemplo, si está vinculado a la implementación de una determinada biblioteca), la siguiente respuesta puede ser útil:
Esta expresión regular coincide con líneas que contienen exactamente 5 dígitos:
^(?=(/D*/d){5}/D*$)
Esta expresión regular coincide con líneas que contienen un espacio opcional:
^(?=[^ ]* ?[^ ]*$)
Si los juntamos y también aseguramos que la cadena contiene solo dígitos y espacios ( [/d ]*$
), obtenemos:
^(?=(/D*/d){5}/D*$)(?=[^ ]* ?[^ ]*$)[/d ]*$
También podría usar [/d ]{5,6}
lugar de [/d ]*
al final de ese patrón, con el mismo efecto.
Explicación:
Esta expresión regular está usando lookaheads . Estas son combinaciones de patrones de ancho cero, lo que significa que ambas partes del patrón están "ancladas" al comienzo de la cadena.
/d
significa "cualquier dígito", y/D
significa "cualquier no dígito ".significa "espacio" y
[^ ]
significa "cualquier no espacio ".La
/D*/d
se repite 5 veces, para asegurar que haya exactamente 5 dígitos en la cadena.
Aquí hay una visualización de la expresión regular en acción:
Tenga en cuenta que si realmente desea que el "espacio opcional" incluya elementos como pestañas, entonces podría usar /s
y /S
Actualización: Dado que esta pregunta parece haber tenido bastante tracción, quería aclarar algo sobre esta respuesta.
Hay varias soluciones variantes "más simples" para mi respuesta anterior, como:
// Only look for digits and spaces, not "non-digits" and "non-spaces":
^(?=( ?/d){5} *$)(?=/d* ?/d*$)
// Like above, but also simplifying the second lookahead:
^(?=( ?/d){5} *$)/d* ?/d*
// Or even splitting it into two, simpler, problems with an "or" operator:
^(?:/d{5}|(?=/d* /d*$).{6})$
Demos de cada línea arriba: 1 2 3
O incluso, si podemos suponer que la cadena no tiene más de 6 caracteres, incluso esto es suficiente:
^(?:/d{5}|/d* /d*)$
Entonces, con eso en mente, ¿por qué querrías usar la solución original para problemas similares? Porque es genérico Mira de nuevo mi respuesta original, reescrita con espacio libre :
^
(?=(/D*/d){5}/D*$) # Must contain exactly 5 digits
(?=[^ ]* ?[^ ]*$) # Must contain 0 or 1 spaces
[/d ]*$ # Must contain ONLY digits and spaces
Este patrón de uso de look-aheads sucesivos se puede usar en varios escenarios , para escribir patrones que son altamente estructurados y (quizás sorprendentemente) fáciles de extender.
Por ejemplo, supongamos que las reglas han cambiado y ahora desea unir 2-3 espacios, 1 .
y cualquier cantidad de guiones. De hecho, es muy fácil actualizar la expresión regular:
^
(?=(/D*/d){5}/D*$) # Must contain exactly 5 digits
(?=([^ ]* ){2,3}[^ ]*$) # Must contain 2 or 3 spaces
(?=[^.]*/.[^.]*$) # Must contain 1 period
[/d .-]*$ # Must contain ONLY digits, spaces, periods and hyphens
... En resumen, hay soluciones de expresiones regulares "más simples" y, posiblemente, una mejor solución no regex para el problema específico de OP. Pero lo que he proporcionado es un patrón de diseño extensible y genérico para hacer coincidir patrones de esta naturaleza.
Así es como lo haría sin expresiones regulares:
string => [...string].reduce(
([spaces,digits], char) =>
[spaces += char == '' '', digits += //d/.test(char)],
[0,0]
).join(",") == "1,5";