2011-12-21 34 views
13

Estoy aprendiendo reg ex y me gustaría usar una expresión regular en Python para definir solo enteros: números enteros no decimales. Yo podría hacer uno que sólo permite números usando d, sino que también permite que los números decimales, que no quiero:Python regex para entero?

price = TextField(_('Price'),[validators.Regexp('\d', message=_('This is not an integer number, please see the example and try again')),validators.Optional()] 

¿Cómo puedo cambiar el código para permitir sólo números enteros?

Gracias

+1

http://regexlib.com/ es oro para preguntas como éstas – wim

Respuesta

58

trabajo Regexp sobre la base de carácter, y \d significa un solo dígito 0 ... 9 yn de un número decimal.

Una expresión regular que coincide con sólo enteros con signo podría ser por ejemplo

^[-+]?[0-9]+$ 

significa

  1. ^ - inicio de la cadena de
  2. [-+]? - un accesorio opcional (esto es lo que ? medios) signo menos o más
  3. [0-9]+ - uno o más dígitos (el más m edios "uno o más" y [0-9] es otra forma de decir \d)
  4. $ - final de la cadena

Nota: tener el signo considerado parte de la serie está bien sólo si es necesario para analizar sólo el número. Para analizadores sintácticos más generales que manejan expresiones, es mejor dejar el signo fuera del número: las secuencias fuente como 3-2 podrían terminar siendo analizadas como una secuencia de dos enteros en lugar de un entero, un operador y otro entero. En mi experiencia, los números negativos se manejan mejor mediante el plegado constante del operador de negación unaria y un nivel superior.

+0

Un punto menor: '\ d' significa cualquier dígito decimal, por lo que si está utilizando Python 3 coincidirá con algo más que' 0'..'9'. p.ej. 're.match (" \ d "," \ u0665 ")' coincidirá (y también 'int (" \ u0665 ")' da '5'). – Duncan

+0

Esta publicación es para siempre, pero en caso de que alguien nuevo se tropiece con ella, técnicamente el signo menos es un operador (en Python 3), no parte del número entero: de la especificación: "Tenga en cuenta que los literales numéricos no incluyen un signo ; una frase como -1 es en realidad una expresión compuesta por el operador unario '-' y el literal 1 " –

+0

@en_Knight: esto es IMO totalmente irrelevante. Lo que el OP estaba pidiendo es una expresión para aceptar números enteros ** para humanos **, no para Python 3. Si bien tener un "precio" probablemente solo podría calificar para números no negativos, por ejemplo puede tener mucho sentido aceptando enteros negativos para una "diferencia de precio" ... incluso al escribir ese programa de contabilidad usando Python 3. – 6502

8

Es necesario anchor la expresión regular al comienzo y al final de la cadena:

^[0-9]+$ 

Explicación:

^  # Start of string 
[0-9]+ # one or more digits 0-9 
$  # End of string 
+1

Esto no permite enteros negativos ...no estoy seguro de si OP quiere evitarlos – 6502

+0

@ 6502: Bueno, dado que es una validación para un campo de texto de precio, pensé que los enteros positivos tienen más sentido, pero aún +1 para su respuesta bien comentada :) –

+0

En realidad enteros positivos no Tiene mucho sentido para un campo de texto de precio, a menos que el precio esté en centavos. – wim

7

Aparentemente está usando Django.

Probablemente sea mejor que simplemente utilizando models.IntegerField() en lugar de models.TextField(). No solo hará el control por usted, sino que le dará el mensaje de error traducido en varias langs, y arrojará el valor de su tipo en la base de datos al tipo en su código de Python de forma transparente.

0

Prefiero ^[-+]?([1-9]\d*|0)$ porque ^[-+]?[0-9]+$ permite la cadena que comienza con 0.

RE_INT = re.compile(r'^[-+]?([1-9]\d*|0)$') 


class TestRE(unittest.TestCase): 
    def test_int(self): 
     self.assertFalse(RE_INT.match('+')) 
     self.assertFalse(RE_INT.match('-')) 

     self.assertTrue(RE_INT.match('1')) 
     self.assertTrue(RE_INT.match('+1')) 
     self.assertTrue(RE_INT.match('-1')) 
     self.assertTrue(RE_INT.match('0')) 
     self.assertTrue(RE_INT.match('+0')) 
     self.assertTrue(RE_INT.match('-0')) 

     self.assertTrue(RE_INT.match('11')) 
     self.assertFalse(RE_INT.match('00')) 
     self.assertFalse(RE_INT.match('01')) 
     self.assertTrue(RE_INT.match('+11')) 
     self.assertFalse(RE_INT.match('+00')) 
     self.assertFalse(RE_INT.match('+01')) 
     self.assertTrue(RE_INT.match('-11')) 
     self.assertFalse(RE_INT.match('-00')) 
     self.assertFalse(RE_INT.match('-01')) 

     self.assertTrue(RE_INT.match('1234567890')) 
     self.assertTrue(RE_INT.match('+1234567890')) 
     self.assertTrue(RE_INT.match('-1234567890'))