¿Por qué rango no funciona como se esperaba?

Estoy tratando de usar el patrón de rango [01-12] en expresiones regulares para que coincida con dos dígitos mm, pero esto no funciona como se esperaba.

Parece que no entendiste cómo funciona la definición de clases de caracteres en expresiones regulares.

Para que coincida con cualquiera de las cadenas 01 , 02 , 03 , 04 , 05 , 06 , 07 , 08 , 09 , 10 , 11 o 12 , algo como esto funciona:

 0[1-9]|1[0-2] 

Referencias

  • regular-expressions.info/Character Classes
    • Rangos numéricos (tienen muchos ejemplos de cadenas coincidentes interpretadas como rangos numéricos)

Explicación

Una clase de personaje, por sí misma, intenta hacer coincidir uno y exactamente un carácter de la cadena de entrada. [01-12] realmente define [012] , una clase de caracteres que combina un carácter de la entrada con cualquiera de los 3 caracteres 0 , 1 o 2 .

La definición de rango va de 1 a 1 , que incluye solo 1 . Por otro lado, algo como [1-9] incluye 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 .

Los principiantes a menudo cometen los errores de definir cosas como [this|that] . Esto no “funciona”. Esta definición de carácter define [this|a] , es decir, hace coincidir un carácter de la entrada con cualquiera de los 6 caracteres en t , h , i , s , | o a . Es más que probable (this|that) lo que se pretende.

Referencias

  • regular-expressions.info/Brackets para agrupar y alternar con la barra vertical

Cómo se definen los rangos

Entonces, es obvio ahora que un patrón como between [24-48] hours no “funciona”. La clase de caracteres en este caso es equivalente a [248] .

Es decir, - en una definición de clase de carácter no define el rango numérico en el patrón. Los motores Regex en realidad no “entienden” los números en el patrón, con la excepción de la syntax de repetición finita (por ejemplo, a{3,5} coincide entre 3 y 5 a ).

En su lugar, la definición de rango utiliza la encoding ASCII / Unicode de los caracteres para definir los rangos. El carácter 0 está codificado en ASCII como el decimal 48; 9 es 57. Por lo tanto, la definición de carácter [0-9] incluye todos los caracteres cuyos valores están entre el decimal 48 y 57 en la encoding. Bastante sensatamente, por diseño, estos son los personajes 0 , 1 , …, 9 .

Ver también

  • Wikipedia / ASCII

Otro ejemplo: de la A a la Z

Echemos un vistazo a otra definición de clase de carácter común [a-zA-Z]

En ASCII:

  • A = 65, Z = 90
  • a = 97, z = 122

Esto significa que:

  • [a-zA-Z] y [A-Za-z] son equivalentes
  • En la mayoría de los sabores, [aZ] es probable que sea un rango de caracteres ilegales
    • porque a (97) es “mayor que” que Z (90)
  • [Az] es legal, pero también incluye estos seis caracteres:
    • [ (91), \ (92), ] (93), ^ (94), _ (95), “ `(96)

Preguntas relacionadas

  • es la expresión regular [aZ] válida y si es así, entonces es lo mismo que [a-zA-Z]

Una clase de caracteres en expresiones regulares, denotada por la [...] syntax, especifica las reglas para hacer coincidir un solo carácter en la entrada. Como tal, todo lo que escriba entre corchetes especifica cómo hacer coincidir un solo carácter .

Su patrón, [01-12] se divide de la siguiente manera:

  • 0 – unir el dígito simple 0
  • o, 1-1, coincide con un solo dígito en el rango de 1 a 1
  • o, 2, coinciden con un solo dígito 2

Entonces, básicamente, todo lo que estás combinando es 0, 1 o 2.

Para hacer la coincidencia que desea, haciendo coincidir dos dígitos, que van desde 01-12 como números, debe pensar en cómo se verán como texto.

Tienes:

  • 01-09 (es decir, el primer dígito es 0, el segundo dígito es 1-9)
  • 10-12 (es decir, el primer dígito es 1, el segundo dígito es 0-2)

Luego tendrá que escribir una expresión regular para eso, que puede verse así:

  +-- a 0 followed by 1-9 | | +-- a 1 followed by 0-2 | | < -+--> < -+--> 0[1-9]|1[0-2] ^ | +-- vertical bar, this roughly means "OR" in this context 

Tenga en cuenta que si intenta combinarlos para obtener una expresión más corta, se producirá un error al dar coincidencias de falso positivo para la entrada no válida.

Por ejemplo, el patrón [0-1][0-9] básicamente coincidiría con los números 00-19, que es un poco más de lo que desea.

Traté de encontrar una fuente definitiva para obtener más información sobre las clases de caracteres, pero por ahora todo lo que puedo darte es esta Google Query for Regex Character Classes . Con suerte, podrá encontrar más información allí para ayudarlo.

Esto también funciona:

^([1-9]|[0-1][0-2])$

[1-9] coincide con dígitos simples entre 1 y 9

[0-1][0-2] coincide con los dígitos dobles entre 10 y 12

Aquí hay algunos buenos ejemplos

Como Polygenelubricants dice que el suyo buscaría 0 | 1-1 | 2 en lugar de lo que desea, debido al hecho de que las clases de caracteres (las cosas en []) coinciden con los caracteres en lugar de las cadenas.

Los [] s en una expresión regular denotan una clase de personaje . Si no se especifican rangos, implícitamente o s todos los caracteres dentro de él juntos. Por lo tanto, [abcde] es lo mismo que (a|b|c|d|e) , excepto que no captura nada; coincidirá con cualquiera de a , b , c , d o e . Todo un rango indica es un conjunto de caracteres ; [ac-eg] dice “hacer coincidir cualquiera de: a ; cualquier carácter entre c y e ; o g “. Por lo tanto, su coincidencia dice “hacer coincidir cualquiera de: 0 ; cualquier carácter entre 1 y 1 ( es decir , solo 1 ); o 2 .

Su objective es, evidentemente, especificar un rango numérico: cualquier número entre 01 y 12 escrito con dos dígitos. En este caso específico, puede hacer coincidir con 0[1-9]|1[0-2] : ya sea un 0 seguido de cualquier dígito entre 1 y 9 , o un 1 seguido de cualquier dígito entre 0 y 2 . En general, puede transformar cualquier rango numérico en una expresión regular válida de una manera similar. Sin embargo, puede haber una opción mejor que las expresiones regulares, o una función o módulo existente que pueda construir la expresión regular para usted. Depende de tu idioma

Utilizar esta:

 0?[1-9]|1[012] 
  • 07: válido
  • 7: válido
  • 0: no coincide
  • 00: no coincide
  • 13: no coincide
  • 21: no coincide

Para probar un patrón como 07/2018 usa esto:

 /^(0?[1-9]|1[012])\/([2-9][0-9]{3})$/ 

(Rango de fechas entre 01/2000 a 12/9999)

Para resolver esto, puede usar /^[0-1][0-9]$/; Y si solo desea del 01 al 12 , debe verificar dos condiciones:

Si el valor es 00 usando instrucción if :

 if(thevale=="00") { // message to user...not allowed } 

y:

 if(thevalue >=13) { // message to user...not allowed } 

Código de muestra en Javascript:

 function CheckMonth(txtBox) { var ex = /^[0-1][0-9]$/; if (txtBox.value.trim() != "") { if (txtBox.value.trim() == "00") { alert('Please enter valid numbers.'); txtBox.value = ""; txtBox.focus(); } else if (ex.test(txtBox.value.trim()) == false) { alert('Please enter valid numbers.'); txtBox.value = ""; txtBox.focus(); } else if (parseInt(txtBox.value.trim()) >= 13) { alert('Please enter valid numbers.'); txtBox.value = ""; txtBox.focus(); } } }