2011-12-21 40 views
13

Tôi đang học reg cũ và tôi muốn sử dụng cụm từ thông dụng trong Python để chỉ xác định số nguyên - toàn bộ số không phải số thập phân. Tôi có thể làm cho một trong những chỉ cho phép số bằng cách sử dụng d, nhưng nó cũng cho phép số thập phân mà tôi không muốn:Python regex cho số nguyên?

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

Làm thế nào tôi có thể thay đổi mã để chỉ cho phép số nguyên?

Cảm ơn bạn

+1

http://regexlib.com/ là vàng cho các câu hỏi như thế này – wim

Trả lời

58

biểu thức chính quy làm việc trên cơ sở nhân vật, và \d có nghĩa là một chữ số duy nhất 0 ... 9 và n ot một số thập phân.

Một biểu thức chính quy phù hợp với chỉ số nguyên với một dấu hiệu có thể là ví dụ

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

nghĩa

  1. ^ - khởi đầu của chuỗi
  2. [-+]? - một tùy chọn (đây là những gì ? phương tiện) dấu trừ hoặc dấu cộng
  3. [0-9]+ - một hoặc nhiều chữ số (dấu cộng m eans "một hoặc nhiều" và [0-9] là một cách khác để nói \d)
  4. $ - Cuối chuỗi

Lưu ý: có dấu hiệu được coi là một phần của số là ok chỉ khi bạn cần phải phân tích chỉ số. Đối với các trình phân tích cú pháp tổng quát hơn xử lý các biểu thức tốt hơn là để lại dấu hiệu của số: các luồng nguồn như 3-2 có thể được phân tích cú pháp dưới dạng một chuỗi gồm hai số nguyên thay vì số nguyên, toán tử và số nguyên khác. Số âm sau đó trong kinh nghiệm của tôi được xử lý tốt hơn bằng cách gấp liên tục của toán tử phủ định đơn nhất và mức cao hơn.

+0

Một điểm nhỏ: '\ d' có nghĩa là bất kỳ chữ số thập phân nào, vì vậy nếu bạn đang sử dụng Python 3, nó sẽ khớp với nhiều hơn' 0'..'9'. ví dụ. 're.match (" \ d "," \ u0665 ")' sẽ khớp (và cũng 'int (" \ u0665 ")' cho '5'). – Duncan

+0

Bài đăng này là từ trước đây, nhưng trong trường hợp ai đó mới tình cờ gặp nó, về mặt kỹ thuật dấu trừ là toán tử (trong Python 3), không phải là một phần của số nguyên: từ spec .: "Lưu ý rằng chữ số không bao gồm dấu một cụm từ như -1 thực sự là một biểu thức bao gồm toán tử đơn nhất '-' và chữ 1 " –

+0

@en_Knight: đây là IMO hoàn toàn không liên quan. Những gì OP được yêu cầu là một biểu thức để chấp nhận số nguyên ** cho con người **, không cho Python 3. Trong khi có một "giá" có thể chỉ đủ điều kiện cho các số không âm, ví dụ như nó có thể thực hiện rất nhiều ý nghĩa chấp nhận số nguyên âm cho "chênh lệch giá" ... ngay cả khi viết chương trình kế toán đó bằng Python 3. – 6502

8

Bạn cần phải anchor regex vào lúc bắt đầu và kết thúc của chuỗi:

^[0-9]+$ 

Giải thích:

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

Điều này không cho phép số nguyên âm ...không chắc chắn nếu OP muốn tránh chúng – 6502

+0

@ 6502: Vâng, vì nó là một xác nhận cho một trường văn bản giá, tôi nghĩ số nguyên dương có ý nghĩa hơn, nhưng vẫn +1 cho câu trả lời của bạn cũng bình luận :) –

+0

Thực sự tích cực số nguyên don ' t có ý nghĩa nhiều đối với trường văn bản giá, trừ khi giá bằng xu. – wim

7

Bạn đang sử dụng Django.

Có lẽ bạn nên sử dụng models.IntegerField() thay vì models.TextField(). Nó sẽ không chỉ kiểm tra cho bạn, nhưng nó sẽ cung cấp cho bạn thông báo lỗi được dịch trong nhiều lang, và nó sẽ truyền giá trị từ kiểu của nó trong cơ sở dữ liệu đến kiểu mã Python của bạn một cách minh bạch.

0

Tôi thích ^[-+]?([1-9]\d*|0)$^[-+]?[0-9]+$ cho phép chuỗi bắt đầu bằng 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'))