RegEx để phù hợp với Mã bưu điện của Vương quốc Anh


185

Tôi sau một regex sẽ xác nhận mã bưu chính phức tạp đầy đủ của Anh chỉ trong một chuỗi đầu vào. Tất cả các hình thức mã bưu điện không phổ biến phải được bảo hiểm cũng như thông thường. Ví dụ:

Diêm

  • CW3 9SS
  • SE5 0EG
  • SE50EG
  • se5 0eg
  • WC2H 7LT

Không có trận đấu

  • aWC2H 7LT
  • WC2H 7LTa
  • WC2H

Làm thế nào để tôi giải quyết vấn đề này?


2
@axrwkr trông không hữu ích
Kieran Benton

8
Xác thực mã bưu điện của Vương quốc Anh - JavaScript và PHP Tôi không thể có câu trả lời được chấp nhận để khớp với mã bưu điện hợp lệ nhưng tôi đã tìm thấy mã này và nó phù hợp với mã bưu điện hợp lệ. Để xác thực phía máy khách, phiên bản JavaScript có thể được sử dụng, để xác thực phía máy chủ, việc viết lại JavaScript dưới dạng C # khá đơn giản. Nó thậm chí còn định dạng lại mã bưu điện để có một khoảng trắng, vì vậy nếu bạn nhập mã bưu điện là W1A1AA, ngoài việc xác thực, nó sẽ định dạng lại thành W1A 1AA. Nó thậm chí còn liên quan đến các mã bưu điện bất thường trong các lãnh thổ khác nhau của Anh.

2
Liên kết được cung cấp không hoạt động đối với các định dạng "AA1A 1AA". Tham khảo: DHL.com.tw/content/dam/doads/tw/express/forms/iêng
Anthony Scaife

1
Nếu bạn chỉ đơn giản muốn xác thực mã bưu điện, chúng tôi sẽ cung cấp điểm cuối xác thực API REST miễn phí (yêu cầu đăng ký) - developers.alliescomputing.com/postcoder-web-api/address-lookup/
trộm

1
Câu hỏi hay. Tôi nghĩ rằng nó sẽ có giá trị bao gồm một mã bưu chính trung tâm của Manchester như "M1 3HZ" trong danh sách các ví dụ không phổ biến của bạn cần phải khớp. Nhiều người không biết về combo 1 chữ cái 1 số.
Martin Joiner

Câu trả lời:


207

Tôi khuyên bạn nên xem Tiêu chuẩn Dữ liệu của Chính phủ Vương quốc Anh cho các mã bưu điện [liên kết hiện đã chết; lưu trữ XML , xem Wikipedia để thảo luận]. Có một mô tả ngắn gọn về dữ liệu và lược đồ xml đính kèm cung cấp một biểu thức chính quy. Nó có thể không chính xác những gì bạn muốn nhưng sẽ là một điểm khởi đầu tốt. RegEx khác với XML một chút, vì ký tự P ở vị trí thứ ba ở định dạng A9A 9AA được cho phép theo định nghĩa đã cho.

RegEx do Chính phủ Anh cung cấp là:

([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9][A-Za-z]?))))\s?[0-9][A-Za-z]{2})

Như đã chỉ ra trong cuộc thảo luận trên Wikipedia, điều này sẽ cho phép một số mã bưu điện không có thật (ví dụ: những mã bắt đầu từ AA, ZY) và chúng cung cấp một bài kiểm tra nghiêm ngặt hơn mà bạn có thể thử.


52
Và reg đó với một khoảng trắng tùy chọn giữa hai phân đoạn (GIR 0AA) | ((([AZ- [QVX]] [0-9] [0-9]?) | (([AZ- [QVX]] [AZ- [IJZ]] [0-9] [0-9]?) | (([AZ- [QVX]] [0-9] [A-HJKSTUW]) | ([AZ- [QVX]] [ AZ- [IJZ]] [0-9] [ABEHMNPRVWXY])))) \ s? [0-9] [AZ- [CIKMOV]] {2})
gb2d

6
Có thể là một ý tưởng tốt để đưa regex thực tế vào câu trả lời, vì các trang dường như hết hạn hàng năm ...
pauloya

7
Lưu ý rằng regex này dành cho Lược đồ XML, rõ ràng là hơi khác so với các hương vị regex khác
artbristol

6
Tôi không thể làm điều này để làm việc trong JavaScript. Nó chỉ làm việc với các công cụ regex nhất định?
NickG

12
Trên thực tế, họ đã thay đổi nó: Truyền dữ liệu hàng loạt :^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))[0-9][A-Za-z]{2})$
wieczorek1990

85

Có vẻ như chúng tôi sẽ sử dụng ^(GIR ?0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]([0-9ABEHMNPRV-Y])?)|[0-9][A-HJKPS-UW]) ?[0-9][ABD-HJLNP-UW-Z]{2})$, đây là phiên bản sửa đổi một chút của Minglis ở trên.

Tuy nhiên, chúng ta sẽ phải điều tra chính xác các quy tắc là gì, vì các giải pháp khác nhau được liệt kê ở trên dường như áp dụng các quy tắc khác nhau về việc các chữ cái được phép.

Sau một số nghiên cứu, chúng tôi đã tìm thấy một số thông tin. Rõ ràng một trang trên 'govtalk.gov.uk' chỉ cho bạn một đặc điểm kỹ thuật mã bưu điện govtalk-postcodes . Điều này trỏ đến một lược đồ XML tại Lược đồ XML cung cấp câu lệnh 'giả giả regex' của các quy tắc mã bưu điện.

Chúng tôi đã thực hiện điều đó và làm việc với nó một chút để cung cấp cho chúng tôi biểu thức sau:

^((GIR &0AA)|((([A-PR-UWYZ][A-HK-Y]?[0-9][0-9]?)|(([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRV-Y]))) &[0-9][ABD-HJLNP-UW-Z]{2}))$

Điều này làm cho các không gian tùy chọn, nhưng sẽ giới hạn bạn trong một không gian (thay thế '&' bằng '{0,} cho các không gian không giới hạn). Nó giả sử tất cả các văn bản phải viết hoa.

Nếu bạn muốn cho phép viết thường, với bất kỳ số lượng khoảng trắng, hãy sử dụng:

^(([gG][iI][rR] {0,}0[aA]{2})|((([a-pr-uwyzA-PR-UWYZ][a-hk-yA-HK-Y]?[0-9][0-9]?)|(([a-pr-uwyzA-PR-UWYZ][0-9][a-hjkstuwA-HJKSTUW])|([a-pr-uwyzA-PR-UWYZ][a-hk-yA-HK-Y][0-9][abehmnprv-yABEHMNPRV-Y]))) {0,}[0-9][abd-hjlnp-uw-zABD-HJLNP-UW-Z]{2}))$

Điều này không bao gồm các lãnh thổ ở nước ngoài và chỉ thực thi định dạng, KHÔNG tồn tại các khu vực khác nhau. Nó dựa trên các quy tắc sau:

Có thể chấp nhận các định dạng sau:

  • Ăn mặc GIR 0AA
  • A9 9ZZ
  • A99 9ZZ
  • AB9 9ZZ
  • AB99 9ZZ
  • A9C 9ZZ
  • QUẢNG CÁO 9

Ở đâu:

  • 9 có thể là bất kỳ số nào.
  • A có thể là bất kỳ chữ cái nào ngoại trừ Q, V hoặc X.
  • B có thể là bất kỳ chữ cái nào ngoại trừ I, J hoặc Z.
  • C có thể là bất kỳ chữ cái nào ngoại trừ I, L, M, N, O, P, Q, R, V, X, Y hoặc Z.
  • D có thể là bất kỳ chữ cái nào ngoại trừ I, J hoặc Z.
  • E có thể là bất kỳ A, B, E, H, M, N, P, R, V, W, X hoặc Y.
  • Z có thể là bất kỳ chữ cái nào ngoại trừ C, I, K, M, O hoặc V.

Lời chúc tốt nhất

Colin


2
Câu trả lời tuyệt vời, tôi đã thêm vào những người ở nước ngoài^(([gG][iI][rR] {0,}0[aA]{2})|(([aA][sS][cC][nN]|[sS][tT][hH][lL]|[tT][dD][cC][uU]|[bB][bB][nN][dD]|[bB][iI][qQ][qQ]|[fF][iI][qQ][qQ]|[pP][cC][rR][nN]|[sS][iI][qQ][qQ]|[iT][kK][cC][aA]) {0,}1[zZ]{2})|((([a-pr-uwyzA-PR-UWYZ][a-hk-yxA-HK-XY]?[0-9][0-9]?)|(([a-pr-uwyzA-PR-UWYZ][0-9][a-hjkstuwA-HJKSTUW])|([a-pr-uwyzA-PR-UWYZ][a-hk-yA-HK-Y][0-9][abehmnprv-yABEHMNPRV-Y]))) {0,}[0-9][abd-hjlnp-uw-zABD-HJLNP-UW-Z]{2}))$
David Bradshaw

Tại sao chỉ định {0,}thay vì *không giới hạn, không gian tùy chọn?
Mã động vật

74

Gần đây tôi đã đăng tải một câu trả lời cho câu hỏi này trên postcodes Anh cho ngôn ngữ R . Tôi phát hiện ra rằng mẫu regex của Chính phủ Vương quốc Anh là không chính xác và không xác nhận đúng một số mã bưu điện. Thật không may, nhiều câu trả lời ở đây dựa trên mẫu không chính xác này.

Tôi sẽ phác thảo một số vấn đề dưới đây và cung cấp một biểu thức chính quy được sửa đổi thực sự hoạt động.


Ghi chú

Câu trả lời của tôi (và các biểu thức chính quy nói chung):

  • Chỉ xác nhận các định dạng mã bưu điện .
  • Không đảm bảo rằng một mã bưu chính tồn tại hợp pháp .

Nếu bạn không quan tâm đến regex xấu và chỉ muốn bỏ qua câu trả lời, hãy cuộn xuống phần Trả lời .

Regex xấu

Các biểu thức chính quy trong phần này không nên được sử dụng.

Đây là regex thất bại mà chính phủ Anh đã cung cấp cho các nhà phát triển (không chắc liên kết này sẽ kéo dài bao lâu, nhưng bạn có thể thấy nó trong tài liệu Chuyển dữ liệu hàng loạt của họ ):

^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))[0-9][A-Za-z]{2})$

Các vấn đề

Vấn đề 1 - Sao chép / Dán

Xem regex đang sử dụng ở đây .

Như nhiều nhà phát triển có thể làm, họ sao chép / dán mã (đặc biệt là các biểu thức thông thường) và dán chúng để mong chúng hoạt động. Mặc dù điều này là lý thuyết tuyệt vời, nhưng nó thất bại trong trường hợp cụ thể này vì sao chép / dán từ tài liệu này thực sự thay đổi một trong các ký tự (khoảng trắng) thành ký tự dòng mới như dưới đây:

^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))
[0-9][A-Za-z]{2})$

Điều đầu tiên mà hầu hết các nhà phát triển sẽ làm chỉ là xóa dòng mới mà không cần suy nghĩ kỹ. Bây giờ regex sẽ không khớp mã bưu điện với khoảng trắng trong chúng (trừ GIR 0AAmã bưu điện).

Để khắc phục sự cố này, nên thay thế ký tự dòng mới bằng ký tự khoảng trắng:

^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$
                                                                                                                                                     ^

Vấn đề 2 - Ranh giới

Xem regex đang sử dụng ở đây .

^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$
^^                     ^ ^                                                                                                                                            ^^

Mã bưu chính regex không đúng cách neo regex. Bất cứ ai sử dụng regex này để xác nhận mã bưu điện có thể ngạc nhiên nếu một giá trị như fooA11 1AAđược thông qua. Đó là bởi vì họ đã thả neo bắt đầu tùy chọn đầu tiên và kết thúc tùy chọn thứ hai (độc lập với nhau), như được chỉ ra trong biểu thức chính thức ở trên.

Điều này có nghĩa là ^(xác nhận vị trí ở đầu dòng) chỉ hoạt động trên tùy chọn đầu tiên ([Gg][Ii][Rr] 0[Aa]{2}), vì vậy tùy chọn thứ hai sẽ xác thực bất kỳ chuỗi nào kết thúc bằng mã bưu điện (bất kể trước đó là gì).

Tương tự, tùy chọn đầu tiên không được neo vào cuối dòng $, do đó GIR 0AAfoocũng được chấp nhận.

^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))[0-9][A-Za-z]{2})$

Để khắc phục vấn đề này, cả hai tùy chọn nên được bọc trong một nhóm khác (hoặc nhóm không bắt giữ) và các neo được đặt xung quanh đó:

^(([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2}))$
^^                                                                                                                                                                      ^^

Vấn đề 3 - Bộ ký tự không đúng

Xem regex đang sử dụng ở đây .

^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$
                                                                                       ^^

Regex bị thiếu -ở đây để chỉ ra một loạt các ký tự. Vì nó đứng, nếu một mã bưu điện có định dạng ANA NAA(trong đó Ađại diện cho một chữ cái và Nđại diện cho một số), và nó bắt đầu bằng bất cứ điều gì khác Ahoặc Z, nó sẽ thất bại.

Điều đó có nghĩa là nó sẽ phù hợp A1A 1AAZ1A 1AA, nhưng không B1A 1AA.

Để khắc phục sự cố này, ký tự -phải được đặt giữa AZtrong bộ ký tự tương ứng:

^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$
                                                                                        ^

Vấn đề 4 - Bộ ký tự tùy chọn sai

Xem regex đang sử dụng ở đây .

^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$
                                                                                                                                        ^

Tôi thề họ thậm chí không kiểm tra điều này trước khi công khai nó trên web. Họ đã đặt sai ký tự tùy chọn. Họ đã thực hiện [0-9]tùy chọn trong tùy chọn phụ thứ tư của tùy chọn 2 (nhóm 9). Điều này cho phép regex khớp với các mã bưu điện được định dạng không chính xác như thế nào AAA 1AA.

Để khắc phục sự cố này, thay vào đó, hãy tạo lớp nhân vật tiếp theo tùy chọn (và sau đó làm cho tập [0-9]hợp khớp chính xác một lần):

^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9][A-Za-z]?)))) [0-9][A-Za-z]{2})$
                                                                                                                                                ^

Vấn đề 5 - Hiệu suất

Hiệu suất trên regex này là cực kỳ kém. Trước hết, họ đặt tùy chọn mẫu ít có khả năng khớp nhất GIR 0AAlúc ban đầu. Có bao nhiêu người dùng có thể sẽ có mã bưu điện này so với bất kỳ mã bưu điện nào khác; Có lẽ không bao giờ? Điều này có nghĩa là mỗi khi regex được sử dụng, nó phải sử dụng hết tùy chọn này trước khi tiếp tục tùy chọn tiếp theo. Để xem hiệu suất bị ảnh hưởng như thế nào, hãy kiểm tra số bước mà regex ban đầu đã thực hiện (35) so với regex tương tự sau khi đã lật các tùy chọn (22).

Vấn đề thứ hai với hiệu suất là do cách cấu trúc toàn bộ regex. Không có điểm quay lại qua từng tùy chọn nếu một thất bại. Cách thức cấu trúc regex hiện tại có thể được đơn giản hóa rất nhiều. Tôi cung cấp một sửa chữa cho điều này trong phần Trả lời .

Bài 6 - Dấu cách

Xem regex đang sử dụng tại đây

Điều này có thể không được coi là một vấn đề , nhưng sẽ gây lo ngại cho hầu hết các nhà phát triển. Các khoảng trắng trong regex không phải là tùy chọn, có nghĩa là người dùng nhập mã bưu điện của họ phải đặt một khoảng trắng trong mã bưu điện. Đây là một sửa chữa dễ dàng bằng cách thêm vào ?sau khoảng trắng để hiển thị chúng tùy chọn. Xem Trả lời để khắc phục.


Câu trả lời

1. Sửa Regex Chính phủ Vương quốc Anh

Sửa chữa tất cả các vấn đề được nêu trong vấn đề phần và đơn giản hóa mô hình mang lại những điều sau đây, ngắn hơn, hoa văn súc tích hơn. Chúng tôi cũng có thể xóa hầu hết các nhóm vì chúng tôi xác nhận toàn bộ mã bưu điện (không phải từng phần riêng lẻ):

Xem regex đang sử dụng tại đây

^([A-Za-z][A-Ha-hJ-Yj-y]?[0-9][A-Za-z0-9]? ?[0-9][A-Za-z]{2}|[Gg][Ii][Rr] ?0[Aa]{2})$

Điều này có thể được rút ngắn hơn nữa bằng cách loại bỏ tất cả các phạm vi khỏi một trong các trường hợp (chữ hoa hoặc chữ thường) và sử dụng cờ không phân biệt chữ hoa chữ thường. Ghi chú : Một số ngôn ngữ không có ngôn ngữ, vì vậy hãy sử dụng ngôn ngữ dài hơn ở trên. Mỗi ngôn ngữ thực hiện cờ không phân biệt chữ hoa chữ thường.

Xem regex đang sử dụng ở đây .

^([A-Z][A-HJ-Y]?[0-9][A-Z0-9]? ?[0-9][A-Z]{2}|GIR ?0A{2})$

Ngắn hơn một lần nữa thay thế [0-9]bằng \d(nếu công cụ regex của bạn hỗ trợ nó):

Xem regex đang sử dụng ở đây .

^([A-Z][A-HJ-Y]?\d[A-Z\d]? ?\d[A-Z]{2}|GIR ?0A{2})$

2. Các mẫu đơn giản hóa

Không đảm bảo các ký tự chữ cái cụ thể, có thể sử dụng các ký tự sau (ghi nhớ các đơn giản hóa từ 1. Sửa lỗi Regex của Chính phủ Vương quốc Anh cũng đã được áp dụng tại đây):

Xem regex đang sử dụng ở đây .

^([A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}|GIR ?0A{2})$

Và thậm chí xa hơn nếu bạn không quan tâm đến trường hợp đặc biệt GIR 0AA:

^[A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}$

3. Các mẫu phức tạp

Tôi sẽ không đề xuất xác minh quá mức mã bưu điện vì Khu vực, Quận và Tiểu huyện mới có thể xuất hiện bất cứ lúc nào. Những gì tôi sẽ đề xuất có khả năng làm, được thêm hỗ trợ cho các trường hợp cạnh. Một số trường hợp đặc biệt tồn tại và được nêu trong bài viết Wikipedia này .

Dưới đây là các biểu thức phức tạp bao gồm các phần phụ của 3. (3.1, 3.2, 3.3).

Liên quan đến các mẫu trong 1. Sửa Chính sách Chính phủ Vương quốc Anh :

Xem regex đang sử dụng tại đây

^(([A-Z][A-HJ-Y]?\d[A-Z\d]?|ASCN|STHL|TDCU|BBND|[BFS]IQQ|PCRN|TKCA) ?\d[A-Z]{2}|BFPO ?\d{1,4}|(KY\d|MSR|VG|AI)[ -]?\d{4}|[A-Z]{2} ?\d{2}|GE ?CX|GIR ?0A{2}|SAN ?TA1)$

Và liên quan đến 2. Các mẫu đơn giản hóa :

Xem regex đang sử dụng tại đây

^(([A-Z]{1,2}\d[A-Z\d]?|ASCN|STHL|TDCU|BBND|[BFS]IQQ|PCRN|TKCA) ?\d[A-Z]{2}|BFPO ?\d{1,4}|(KY\d|MSR|VG|AI)[ -]?\d{4}|[A-Z]{2} ?\d{2}|GE ?CX|GIR ?0A{2}|SAN ?TA1)$

3.1 Lãnh thổ hải ngoại của Anh

Bài viết Wikipedia hiện đang nêu (một số định dạng hơi đơn giản):

  • AI-1111: Anguila
  • ASCN 1ZZ: Đảo Ascension
  • STHL 1ZZ: Thánh Helena
  • TDCU 1ZZ: Tristan da Cunha
  • BBND 1ZZ: Lãnh thổ Ấn Độ Dương thuộc Anh
  • BIQQ 1ZZ: Lãnh thổ Nam Cực thuộc Anh
  • FIQQ 1ZZ: Quần đảo Falkland
  • GX11 1ZZ: Gibraltar
  • PCRN 1ZZ: Quần đảo Pitcairn
  • SIQQ 1ZZ: Nam Georgia và Quần đảo Nam Sandwich
  • TKCA 1ZZ: Quần đảo Turks và Caicos
  • BFPO 11: Akrotiri và Dhekelia
  • ZZ 11& GE CX: Bermuda (theo tài liệu này )
  • KY1-1111: Quần đảo Cayman (theo tài liệu này )
  • VG1111: Quần đảo Virgin thuộc Anh (theo tài liệu này )
  • MSR 1111: Montserrat (theo tài liệu này )

Một regex bao gồm tất cả để chỉ phù hợp với Lãnh thổ hải ngoại của Anh có thể trông như thế này:

Xem regex đang sử dụng ở đây .

^((ASCN|STHL|TDCU|BBND|[BFS]IQQ|GX\d{2}|PCRN|TKCA) ?\d[A-Z]{2}|(KY\d|MSR|VG|AI)[ -]?\d{4}|(BFPO|[A-Z]{2}) ?\d{2}|GE ?CX)$

3.2 Bưu điện lực lượng Anh

Mặc dù gần đây họ đã thay đổi nó để phù hợp hơn với hệ thống mã bưu chính của Anh thành BF#(nơi #đại diện cho một số), chúng được coi là mã bưu điện thay thế tùy chọn . Các mã bưu điện này tuân theo (ed) định dạng củaBFPO , theo sau là 1-4 chữ số:

Xem regex đang sử dụng tại đây

^BFPO ?\d{1,4}$

3,3 ông già Noel?

Có một trường hợp đặc biệt khác với ông già Noel (như đã đề cập trong các câu trả lời khác): SAN TA1là một mã bưu điện hợp lệ. Một regex cho điều này rất đơn giản:

^SAN ?TA1$

4
Các mẫu đơn giản hóa là một lựa chọn thực sự tốt để sử dụng. Tôi thấy tốt nhất không nên quá hạn chế với regex vì khi đó bạn cần đảm bảo nó được cập nhật với bất kỳ thay đổi nào hoặc bạn có thể khiến người dùng rất tức giận. Tôi cảm thấy tốt hơn khi kết hợp một cách lỏng lẻo với regex đơn giản hóa để loại bỏ các lỗi rõ ràng và sau đó áp dụng các kiểm tra tiếp theo như tra cứu địa chỉ (hoặc email xác nhận trong trường hợp email regex) để xác nhận tính hợp lệ.
James Coyle

2
Phân tích tuyệt vời và kỹ lưỡng.
Steve

1
Câu trả lời rực rỡ trên nhiều cấp độ. Cuối cùng, tôi đã đi với mô hình đơn giản hóa thứ 2 của bạn. Vì tôi thực sự có một DB với tất cả các mã bưu điện ở Anh, tôi chỉ cần một lượt đi đầu tiên để xem chuỗi địa chỉ có khả năng chứa mã bưu điện hợp lệ hay không, vì vậy tôi không quan tâm đến các thông báo sai (vì việc tra cứu thực tế sẽ khắc phục chúng) , nhưng tôi quan tâm đến những tiêu cực sai. Và tốc độ cũng có vấn đề.
John Powell

Có rất nhiều vấn đề với hệ thống mã bưu chính của Vương quốc Anh, rõ ràng được tạo ra bởi ủy ban trước kỷ nguyên máy tính, nhưng vấn đề về độ dài và không gian thay đổi là một trong những vấn đề nguy hiểm nhất. Tôi đã thấy tất cả các cách khủng khiếp, bao gồm cả mã bưu điện đệm như E1 5JX đến E1 5JX, tức là có ba khoảng trắng, để nó phù hợp độc đáo với SW18 5HA trong Excel (chèn phần mềm không phù hợp để chọn quản lý địa chỉ). Giải pháp lành mạnh duy nhất, IMHO, là loại bỏ tất cả các khoảng trắng, sao cho mã bưu điện là một chuỗi duy nhất trước khi nó đến bất kỳ nơi nào gần Elastic, Solr, Postgres, v.v.
John Powell

45

Không có thứ gọi là biểu thức chính quy mã bưu chính toàn diện của Vương quốc Anh có khả năng xác nhận mã bưu điện. Bạn có thể kiểm tra xem mã bưu điện có đúng định dạng hay không bằng cách sử dụng biểu thức chính quy; không phải là nó thực sự tồn tại

Mã bưu điện là phức tạp tùy ý và liên tục thay đổi. Chẳng hạn, mã ngoài W1không, và có thể không bao giờ có mọi số từ 1 đến 99 cho mọi khu vực mã bưu điện.

Bạn không thể mong đợi những gì hiện tại là sự thật mãi mãi. Một ví dụ, vào năm 1990, Bưu điện đã quyết định rằng Aberdeen đang trở nên hơi đông đúc. Họ đã thêm 0 vào cuối AB1-5, biến nó thành AB10-50 và sau đó tạo ra một số mã bưu điện ở giữa chúng.

Bất cứ khi nào một đường phố mới được xây dựng, một mã bưu điện mới được tạo ra. Đó là một phần của quá trình xin phép xây dựng; chính quyền địa phương có nghĩa vụ phải cập nhật thông tin này với Bưu điện (không phải tất cả họ đều làm như vậy).

Hơn nữa, như được lưu ý bởi một số người dùng khác, có các mã bưu điện đặc biệt như Girobank, GIR 0AA và thư gửi cho ông già Noel, SAN TA1 - bạn có thể không muốn đăng bất cứ điều gì ở đó nhưng nó không xuất hiện được bao phủ bởi bất kỳ câu trả lời khác.

Sau đó, có mã bưu điện BFPO, hiện đang thay đổi sang định dạng chuẩn hơn . Cả hai định dạng sẽ hợp lệ. Cuối cùng, có các lãnh thổ hải ngoại nguồn Wikipedia .

+ ---------- + -------------------------------------- -------- +
| Mã bưu điện | Địa điểm |
+ ---------- + -------------------------------------- -------- +
| AI-2640 | Anguilla |
| ASCN 1ZZ | Đảo Thăng Thiên |
| STHL 1ZZ | Thánh Helena |
| TDCU 1ZZ | Tristan da Cunha |
| BBND 1ZZ | Lãnh thổ Ấn Độ Dương Anh |
| BIQQ 1ZZ | Lãnh thổ Nam Cực của Anh |
| FIQQ 1ZZ | Quần đảo Falkland |
| GX11 1AA | Gibraltar |
| PCRN 1ZZ | Quần đảo Pitcairn |
| SIQQ 1ZZ | Nam Georgia và Quần đảo Nam Sandwich |
| TKCA 1ZZ | Quần đảo Turks và Caicos |
+ ---------- + -------------------------------------- -------- +

Tiếp theo, bạn phải tính đến việc Vương quốc Anh "xuất khẩu" hệ thống mã bưu chính của mình đến nhiều nơi trên thế giới. Bất cứ điều gì xác nhận mã bưu điện "Vương quốc Anh" cũng sẽ xác nhận mã bưu điện của một số quốc gia khác.

Nếu bạn muốn xác thực mã bưu điện ở Anh, cách an toàn nhất là sử dụng tra cứu mã bưu điện hiện tại. Có một số tùy chọn:

  • Khảo sát bản đồ phát hành Code-Point Open theo giấy phép dữ liệu mở. Nó sẽ rất chậm so với thời gian nhưng nó miễn phí. Điều này sẽ (có lẽ - tôi không thể nhớ) không bao gồm dữ liệu Bắc Ailen vì Khảo sát bản đồ không có tiền gửi ở đó. Lập bản đồ ở Bắc Ireland được thực hiện bởi Khảo sát bản đồ của Bắc Ireland và họ có sản phẩm Con trỏ riêng, trả tiền, riêng . Bạn có thể sử dụng cái này và nối thêm một số thứ không được bao phủ khá dễ dàng.

  • Royal Mail phát hành Tệp Địa chỉ Mã bưu điện (PAF) , bao gồm BFPO mà tôi không chắc Mã mở điểm. Nó được cập nhật thường xuyên nhưng tốn tiền (đôi khi chúng có thể hoàn toàn có ý nghĩa về điều đó). PAF bao gồm địa chỉ đầy đủ thay vì chỉ mã hóa và đi kèm với Hướng dẫn lập trình viên riêng . Nhóm người dùng dữ liệu mở (ODUG) hiện đang vận động để PAF được phát hành miễn phí, đây là một mô tả về vị trí của họ .

  • Cuối cùng, có AddressBase . Đây là sự hợp tác giữa Khảo sát bản quyền, Chính quyền địa phương, Royal Mail và một công ty phù hợp để tạo một thư mục chính xác tất cả thông tin về tất cả các địa chỉ của Vương quốc Anh (họ cũng khá thành công). Được trả tiền nhưng nếu bạn làm việc với Cơ quan địa phương, bộ chính phủ hoặc dịch vụ chính phủ thì họ sẽ được sử dụng miễn phí. Có rất nhiều thông tin hơn là chỉ bao gồm các mã bưu điện.


việc tìm kiếm nghe có vẻ thú vị
SuperUberDuper

2
Mặc dù đây không phải là câu trả lời mà op đang tìm kiếm, nhưng nó có lẽ là hữu ích nhất. Điều này sẽ khuyến khích tôi thư giãn các quy tắc kiểm tra mà tôi sẽ làm.
John Hunt

22

Tôi đã xem xét một số câu trả lời ở trên và tôi khuyên bạn không nên sử dụng mẫu từ câu trả lời của @ Dan (c. 15/12/2016) , vì nó đánh dấu không chính xác gần như 0,4% mã bưu điện hợp lệ là không hợp lệ, trong khi những người khác thì không .

Khảo sát bản đồ cung cấp dịch vụ được gọi là Code Point Open, trong đó:

chứa danh sách tất cả các đơn vị mã bưu điện hiện tại ở Vương quốc Anh

Tôi đã chạy từng regex ở trên với danh sách đầy đủ các mã bưu điện (ngày 6 tháng 7 năm 13) từ dữ liệu này bằng cách sử dụng grep:

cat CSV/*.csv |
    # Strip leading quotes
    sed -e 's/^"//g' |
    # Strip trailing quote and everything after it
    sed -e 's/".*//g' |
    # Strip any spaces
    sed -E -e 's/ +//g' |
    # Find any lines that do not match the expression
    grep --invert-match --perl-regexp "$pattern"

Có tổng số 1.686.202 mã bưu điện.

Sau đây là số lượng mã bưu điện hợp lệ không khớp với nhau $pattern:

'^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]?[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$'
# => 6016 (0.36%)
'^(GIR ?0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]([0-9ABEHMNPRV-Y])?)|[0-9][A-HJKPS-UW]) ?[0-9][ABD-HJLNP-UW-Z]{2})$'
# => 0
'^GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|BX|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4}$'
# => 0

Tất nhiên, những kết quả này chỉ xử lý các mã bưu điện hợp lệ được gắn cờ không chính xác là không hợp lệ. Vì thế:

'^.*$'
# => 0

Tôi không nói gì về mẫu nào là tốt nhất liên quan đến việc lọc ra các mã bưu điện không hợp lệ.


1
Đây không phải là những gì tôi nói trong câu trả lời của tôi và nếu bạn đang đi xuống tuyến đường không chắc chắn, có lẽ bạn nên làm tất cả và cập nhật nếu ai đó thay đổi câu trả lời của họ? Nếu không, ít nhất hãy tham khảo ngày chỉnh sửa cuối cùng của câu trả lời bạn đã lấy từ đó để mọi người có thể biết liệu nó có bị thay đổi hay không.
Ben

Điểm công bằng. Chỉnh sửa cho phù hợp. Tôi nghĩ rằng nó bổ sung vào cuộc thảo luận để chỉ ra rằng hầu hết các mẫu này không loại trừ bất kỳ mã CPO nào, nhưng câu trả lời được đánh giá cao nhất (regex hợp lệ) thì có. Độc giả tương lai: lưu ý rằng kết quả của tôi có thể sẽ bị lỗi thời.
RichardTowers

17
^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$

Biểu thức chính quy để phù hợp với mã bưu điện hợp lệ của Vương quốc Anh. Trong hệ thống bưu chính của Vương quốc Anh, không phải tất cả các chữ cái đều được sử dụng ở tất cả các vị trí (giống với biển đăng ký xe) và có nhiều quy tắc khác nhau để chi phối việc này. Regex này có tính đến các quy tắc. Chi tiết về các quy tắc: Nửa đầu của mã bưu điện Các định dạng hợp lệ [AZ] [AZ] [0-9] [AZ] [AZ] [AZ] [0-9] [0-9] [AZ] [0-9] [ 0-9] [AZ] [AZ] [0-9] [AZ] [AZ] [AZ] [AZ] [0-9] [AZ] [AZ] [0-9] Vị trí ngoại lệ - Đầu tiên. Chống chỉ định - QVX không được sử dụng Vị trí - Thứ hai. Chống chỉ định - IJZ không được sử dụng ngoại trừ ở Vị trí GIR 0AA - Thứ ba. Ràng buộc - AEHMNPRTVXY chỉ được sử dụng Vị trí - Forth. Chống chỉ định - ABEHMNPRVWXY Nửa sau của mã bưu điện Các định dạng hợp lệ [0-9] [AZ] [AZ] Vị trí ngoại lệ - Thứ hai và Thứ ba. Chống chỉ định - CIKMOV không được sử dụng

http://regexlib.com/REDetails.aspx?regapi_id=260


1
Không biết tại sao mọi người lại đánh giá thấp câu trả lời này - đó là regex chính xác
Ollie

Regex không hoạt động đối với mã bưu chính "YO31" và "YO31 1" trong Javscript.
Pratik Khadloya

9
Tôi không nghĩ rằng điều này là chính xác, vì regex đưa ra mâu thuẫn với mô tả và gợi ý bạn có thể có mã bưu điện bắt đầu 0-9, mà bạn không thể
Luigi Plinge

4
Regex này thất bại với khoảng 6000 mã bưu điện hợp lệ, vì vậy tôi khuyên bạn nên chống lại nó. Xem câu trả lời của tôi .
RichardTowers

điều này không thành công trên bất kỳ mã bưu điện nào bằng chữ thường hoặc không có khoảng trống cho tôi
Dancer

14

Theo bảng Wikipedia này

nhập mô tả hình ảnh ở đây

Mẫu này bao gồm tất cả các trường hợp

(?:[A-Za-z]\d ?\d[A-Za-z]{2})|(?:[A-Za-z][A-Za-z\d]\d ?\d[A-Za-z]{2})|(?:[A-Za-z]{2}\d{2} ?\d[A-Za-z]{2})|(?:[A-Za-z]\d[A-Za-z] ?\d[A-Za-z]{2})|(?:[A-Za-z]{2}\d[A-Za-z] ?\d[A-Za-z]{2})

Khi sử dụng nó trên Android \ Java, hãy sử dụng \ d


Tôi thấy đây là câu trả lời dễ đọc nhất, mặc dù nó chỉ tìm dạng mã bưu điện, thay vì mã hợp lệ thực tế theo các giải pháp lấy thông tin từ trang web gov.uk, nhưng nó đủ tốt cho trường hợp sử dụng của tôi. Sau khi chơi với nó một chút (bằng python), tôi đã giới thiệu nó với một regex nhỏ gọn hơn nhưng tương đương, cũng cho phép một không gian tùy chọn: ([a-zA-Z] (?: (?: [A-zA- Z]? \ D [a-zA-Z]) | (?: \ D {1,2}) | (?: [A-zA-Z] \ d {1,2})) \ W? [0 -9] [a-zA-Z] {2})
Richard J

14

Hầu hết các câu trả lời ở đây không hoạt động đối với tất cả các mã bưu điện tôi có trong cơ sở dữ liệu của mình. Cuối cùng tôi đã tìm thấy một thứ hợp lệ với tất cả, sử dụng regex mới do chính phủ cung cấp:

https://www.gov.uk/g chính / uploads / system / uploads / attachment_data / file / 413338 / Boy_Data_Transfer_-_additable_validation_valid_from_March_2015.pdf

Nó không có trong bất kỳ câu trả lời nào trước đây vì vậy tôi đăng nó ở đây trong trường hợp họ gỡ liên kết xuống:

^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$

CẬP NHẬT: Cập nhật regex như được chỉ ra bởi Jamie Bull. Không chắc chắn đó là lỗi sao chép của tôi hay đó là lỗi trong regex của chính phủ, liên kết đã ngừng hoạt động ...

CẬP NHẬT: Như ctwheels được tìm thấy, regex này hoạt động với hương vị regex javascript. Xem bình luận của anh ấy cho một hoạt động với hương vị pcre (php).


1
^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$nên ^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$- phát hiện sự khác biệt ;-)
Jamie Bull

1
Tại chỗ trên! Cập nhật câu trả lời của tôi. Cảm ơn!
Jesús Carrera

2
Đây là câu trả lời duy nhất ở đây đã hoạt động trong regexr.com và Notepad ++. Mặc dù, tôi đã thay đổi nó thành ([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) ?[0-9][A-Za-z]{2})(loại bỏ ^$thêm vào ?sau khoảng trắng ) cho regexr.com để tìm nhiều hơn một kết quả và cho cả hai để tìm một kết quả không có ngăn cách không gian.
huyền thoại

@ctwheels regex này là dành cho hương vị javascript. Nếu liên kết không thành công, bạn chọn javascript, nó sẽ hoạt động. Đó là một bắt tuyệt vời và tôi sẽ cập nhật câu trả lời của tôi.
Jesús Carrera

1
Regex đăng trong tài liệu vốn đã không chính xác. Toàn bộ biểu thức nên được bọc trong một nhóm không bắt (?:)và sau đó neo được đặt xung quanh nó. Xem nó thất bại ở đây . Để biết thêm thông tin, xem câu trả lời của tôi ở đây . ^(?:([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2}))$là biểu thức chính quy được sửa.
ctwheels

12

Một bài viết cũ nhưng vẫn còn khá cao trong kết quả google nên tôi nghĩ tôi sẽ cập nhật. Tài liệu ngày 14 tháng 10 này định nghĩa biểu thức chính quy của mã bưu điện Anh là:

^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([**AZ**a-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$

từ:

https://www.gov.uk/g chính / uploads / system / uploads / atadment

Tài liệu cũng giải thích logic đằng sau nó. Tuy nhiên, nó có lỗi (được in đậm) và cũng cho phép viết thường, mặc dù pháp lý là không bình thường, vì vậy phiên bản sửa đổi:

^(GIR 0AA)|((([A-Z][0-9]{1,2})|(([A-Z][A-HJ-Y][0-9]{1,2})|(([A-Z][0-9][A-Z])|([A-Z][A-HJ-Y][0-9]?[A-Z])))) [0-9][A-Z]{2})$

Điều này hoạt động với các mã bưu chính mới của London (ví dụ W1D 5LH) mà các phiên bản trước không có.


Có vẻ như lỗi bạn tô đậm đã được sửa trong tài liệu nhưng tôi vẫn thích biểu thức thông thường của bạn vì nó dễ đọc hơn.
Giáo sư lập trình

5
Điều duy nhất tôi muốn nói là làm cho không gian tùy chọn bằng cách thay đổi không gian thành \ s? vì không gian không phải là một yêu cầu cho nó dễ đọc.
Giáo sư lập trình

Regex đăng trong tài liệu vốn đã không chính xác. Toàn bộ biểu thức nên được bọc trong một nhóm không bắt (?:)và sau đó neo được đặt xung quanh nó. Xem nó thất bại ở đây . Để biết thêm thông tin, xem câu trả lời của tôi ở đây . ^(?:([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2}))$là biểu thức chính quy được sửa.
ctwheels

10

Đây là regex Google phục vụ trên miền i18napis.appspot.com của họ :

GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|BX|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4}

10

Mã bưu điện có thể thay đổi và cách duy nhất để xác thực mã bưu điện là có danh sách đầy đủ mã bưu điện và xem nó có ở đó không.

Nhưng các biểu thức thông thường rất hữu ích vì chúng:

  • dễ sử dụng và thực hiện
  • là ngắn
  • chạy nhanh
  • khá dễ bảo trì (so với danh sách đầy đủ các mã bưu điện)
  • vẫn bắt hầu hết các lỗi đầu vào

Nhưng những biểu hiện thông thường có xu hướng khó duy trì, đặc biệt là đối với người không nghĩ ra nó ngay từ đầu. Vì vậy, nó phải là:

  • càng dễ hiểu càng tốt
  • bằng chứng tương lai

Điều đó có nghĩa là hầu hết các biểu thức chính quy trong câu trả lời này không đủ tốt. Ví dụ: tôi có thể thấy rằng [A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRV-Y]nó sẽ khớp với một khu vực mã bưu điện có dạng AA1A - nhưng sẽ rất đau nếu một khu vực mã bưu chính mới được thêm vào, bởi vì thật khó để hiểu khu vực mã bưu chính nào phù hợp.

Tôi cũng muốn biểu thức chính quy của mình khớp với nửa đầu và nửa sau của mã bưu điện dưới dạng khớp được ngoặc đơn.

Vì vậy, tôi đã đưa ra điều này:

(GIR(?=\s*0AA)|(?:[BEGLMNSW]|[A-Z]{2})[0-9](?:[0-9]|(?<=N1|E1|SE1|SW1|W1|NW1|EC[0-9]|WC[0-9])[A-HJ-NP-Z])?)\s*([0-9][ABD-HJLNP-UW-Z]{2})

Trong định dạng PCRE, nó có thể được viết như sau:

/^
  ( GIR(?=\s*0AA) # Match the special postcode "GIR 0AA"
    |
    (?:
      [BEGLMNSW] | # There are 8 single-letter postcode areas
      [A-Z]{2}     # All other postcode areas have two letters
      )
    [0-9] # There is always at least one number after the postcode area
    (?:
      [0-9] # And an optional extra number
      |
      # Only certain postcode areas can have an extra letter after the number
      (?<=N1|E1|SE1|SW1|W1|NW1|EC[0-9]|WC[0-9])
      [A-HJ-NP-Z] # Possible letters here may change, but [IO] will never be used
      )?
    )
  \s*
  ([0-9][ABD-HJLNP-UW-Z]{2}) # The last two letters cannot be [CIKMOV]
$/x

Đối với tôi đây là sự cân bằng hợp lý giữa việc xác nhận càng nhiều càng tốt, đồng thời chứng minh trong tương lai và cho phép bảo trì dễ dàng.


Không chắc chắn lý do tại sao bạn đã bỏ phiếu - điều này hoạt động với tất cả các mã bưu điện hợp lệ mà tôi đã ném vào nó và khoảng trắng mà rất nhiều câu trả lời ở trên không xử lý chính xác. Bất cứ ai sẽ quan tâm để giải thích tại sao?
Jon

1
@ Jon Nó cũng phù hợp khi nhân vật khác sẽ được nối vào đầu hoặc cuối ví dụ aSW1A 1AAasfgphù hợp cho tôi (tôi không downvote mặc dù là nó có vẻ như nó có thể được cố định một cách dễ dàng)
decvalts

9

Tôi đã tìm kiếm một regex mã bưu điện của Anh cho ngày cuối cùng hoặc lâu hơn và tình cờ tìm thấy chủ đề này. Tôi đã làm việc theo cách của mình thông qua hầu hết các đề xuất ở trên và không ai trong số chúng làm việc cho tôi vì vậy tôi đã đưa ra biểu thức chính của mình, theo như tôi biết, nắm bắt tất cả các mã bưu điện hợp lệ của Anh kể từ ngày 13 tháng 1 (theo tài liệu mới nhất từ Thư Hoàng gia).

Regex và một số mã bưu điện đơn giản kiểm tra mã PHP được đăng dưới đây. LƯU Ý: - Nó cho phép các mã bưu điện viết thường hoặc viết thường và dị thường GIR 0AA nhưng để đối phó với sự hiện diện của một khoảng trống ở giữa một mã bưu điện đã nhập, nó cũng sử dụng một chuỗi thông số đơn giản để xóa khoảng trắng trước khi kiểm tra chống lại regex. Bất kỳ sự khác biệt nào ngoài điều đó và chính Royal Mail thậm chí không đề cập đến chúng trong tài liệu của họ (xem http://www.royalmail.com/sites/default/files/docs/pdf/programmers_guide_edition_7_v5.pdf và bắt đầu đọc từ trang 17) !

Lưu ý: Trong tài liệu riêng của Royal Mail (liên kết ở trên) có một sự mơ hồ nhỏ xung quanh vị trí thứ 3 và thứ 4 và các trường hợp ngoại lệ tại chỗ nếu các ký tự này là chữ cái. Tôi đã liên lạc trực tiếp với Royal Mail để xóa nó và nói theo cách riêng của họ "Một lá thư ở vị trí thứ 4 của Bộ luật bên ngoài với định dạng AANA NAA không có ngoại lệ và ngoại lệ vị trí thứ 3 chỉ áp dụng cho chữ cái cuối cùng của Bộ luật bên ngoài với định dạng ANA NAA. " Thẳng từ miệng ngựa!

<?php

    $postcoderegex = '/^([g][i][r][0][a][a])$|^((([a-pr-uwyz]{1}([0]|[1-9]\d?))|([a-pr-uwyz]{1}[a-hk-y]{1}([0]|[1-9]\d?))|([a-pr-uwyz]{1}[1-9][a-hjkps-uw]{1})|([a-pr-uwyz]{1}[a-hk-y]{1}[1-9][a-z]{1}))(\d[abd-hjlnp-uw-z]{2})?)$/i';

    $postcode2check = str_replace(' ','',$postcode2check);

    if (preg_match($postcoderegex, $postcode2check)) {

        echo "$postcode2check is a valid postcode<br>";

    } else {

        echo "$postcode2check is not a valid postcode<br>";

    }

?>

Tôi hy vọng nó sẽ giúp bất cứ ai khác đi qua chủ đề này đang tìm kiếm một giải pháp.


1
Tôi tò mò muốn biết mã bưu điện mẫu nào bị lỗi khi xuất bản?
Zhaph - Ben Duguid

Tôi không thể cung cấp cho bạn một mã bưu điện cụ thể (không có quyền truy cập vào danh sách PAF đầy đủ) nhưng các mã bưu điện có định dạng ANA NAA sẽ có khả năng thất bại vì các chữ cái P và Q được phép ở vị trí thứ 3 và mã bưu điện có định dạng AANA NAA cũng thất bại vì vị trí thứ 4 cho phép tất cả các chữ cái (biểu thức chính quy trong câu trả lời được chấp nhận ở trên không chiếm một trong hai chữ cái này). Như tôi nói tôi chỉ đi theo lời khuyên hiện tại từ Royal Mail - tại thời điểm trả lời ở trên, có lẽ regex đó đã hoàn toàn tuân thủ.
Dan Solo

Cảm ơn vì đã ngẩng cao đầu - Tôi có thể thấy rằng "P" dường như đã được thêm vào ở mức chấp nhận được ở vị trí thứ ba (từ tài liệu được liên kết của bạn), nhưng không phải Q - nhưng bạn đang đọc "vị trí thứ 4 cho phép tất cả các chữ cái" ở đâu? Tài liệu không đề cập đến "vị trí thứ tư" như tôi có thể thấy, vì vậy tôi đã đọc đó là "chữ cái thứ ba bất kể vị trí thực tế".
Zhaph - Ben Duguid

1
Chỉ cần thông báo lại từ nhóm hỗ trợ của Royal Mail và cách giải thích của tôi về các quy tắc là rõ ràng. Một chữ cái ở vị trí thứ 4 của Mã hướng ngoại (ví dụ AANA NAA) không có ngoại lệ và ngoại lệ vị trí thứ 3 chỉ áp dụng cho chữ cái cuối cùng (ví dụ ANA NAA). Thẳng từ miệng ngựa.
Dan Solo

1
@DanSolo Regex này sẽ trả về một kết quả khớp đúng cho nửa đầu của một mã bưu điện hợp lệ thiếu mã bên trong, ví dụ SW1Ahoặc BD25không có nửa sau (hoặc ít nhất là nó đã làm cho tôi)
xác định

7

Đây là một biểu thức chính dựa trên định dạng được chỉ định trong các tài liệu được liên kết với câu trả lời của marcj:

/^[A-Z]{1,2}[0-9][0-9A-Z]? ?[0-9][A-Z]{2}$/

Sự khác biệt duy nhất giữa điều đó và thông số kỹ thuật là 2 ký tự cuối cùng không thể ở [CIKMOV] theo thông số kỹ thuật.

Chỉnh sửa: Đây là một phiên bản khác kiểm tra các giới hạn ký tự dấu.

/^[A-Z]{1,2}[0-9][0-9A-Z]? ?[0-9][A-BD-HJLNP-UW-Z]{2}$/

Mã bưu điện ở Anh có nhiều phức tạp hơn nhiều so với việc chấp nhận A-Z- Qkhông bao giờ được phép, Vchỉ được sử dụng một cách tiết kiệm, v.v. tùy thuộc vào vị trí của nhân vật.
Zhaph - Ben Duguid

2
Điều đó có thể không liên quan nếu những gì bạn muốn là kiểm tra cú pháp. Như nhiều người khác đã nhận xét, chỉ có một tra cứu trong cơ sở dữ liệu cập nhật gần như chính xác, và thậm chí sau đó có vấn đề về việc cập nhật cơ sở dữ liệu như thế nào. Vì vậy, đối với tôi, regex trình kiểm tra cú pháp này rõ ràng, đơn giản và hữu ích.
Rick-777

5

Một số regex ở trên là một chút hạn chế. Lưu ý mã bưu điện chính hãng: "W1K 7AA" sẽ không đưa ra quy tắc "Vị trí 3 - AEHMNPRTVXY chỉ được sử dụng" ở trên vì "K" sẽ không được phép.

regex:

^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKPS-UW])[0-9][ABD-HJLNP-UW-Z]{2})$

Có vẻ chính xác hơn một chút, xem bài viết trên Wikipedia có tựa đề 'Mã bưu điện ở Vương quốc Anh' .

Lưu ý rằng regex này chỉ yêu cầu ký tự viết hoa.

Câu hỏi lớn hơn là liệu bạn có đang hạn chế đầu vào của người dùng để chỉ cho phép các mã bưu điện thực sự tồn tại hay bạn chỉ đang cố gắng ngăn người dùng nhập rác hoàn toàn vào các trường mẫu. Kết hợp chính xác mọi mã bưu điện có thể, và chứng minh nó trong tương lai, là một câu đố khó hơn và có lẽ không có giá trị trừ khi bạn là HMRC.


Có vẻ như bưu điện đã chuyển đi, nhưng chính phủ đang bị tụt lại phía sau :(
Zhaph - Ben Duguid

4
Tôi sử dụng cái này: "^ ([Gg] [Ii] [Rr] 0 [Aa] {2}) | ((([A-Za-z] [0-9] {1,2}) | (( [A-Za-z] [A-Ha-hJ-Yj-y] [0-9] {1,2}) | (([A-Za-z] [0-9] [A-Za-z ]) | ([A-Za-z] [A-Ha-hJ-Yj-y] [0-9]? [A-Za-z])))) {0,1} [0-9] [ A-Za-z] {2}) $ "Tôi thích nó vì nó cho phép viết hoa và viết thường và làm cho không gian tùy chọn - tốt hơn cho khả năng sử dụng, nếu không chính xác 100%!
bigtv

4

Dưới đây là cách chúng tôi đã xử lý vấn đề về mã bưu chính của Vương quốc Anh:

^([A-Za-z]{1,2}[0-9]{1,2}[A-Za-z]?[ ]?)([0-9]{1}[A-Za-z]{2})$

Giải trình:

  • mong đợi 1 hoặc 2 ký tự az, tiền phạt trên hoặc dưới
  • mong đợi 1 hoặc 2 số
  • mong đợi 0 hoặc 1 az char, tiền phạt trên hoặc dưới
  • không gian tùy chọn cho phép
  • mong đợi 1 số
  • mong đợi 2 az, tiền phạt trên hoặc dưới

Điều này nhận được hầu hết các định dạng, sau đó chúng tôi sử dụng db để xác thực xem mã bưu điện có thực sự không, dữ liệu này được điều khiển bởi openpoint https://www.ordnancesurvey.co.uk/opendatadoad/products.html

hi vọng điêu nay co ich


Điều này cho phép định dạng AANNA NAA, không hợp lệ.
ctwheels

Do đó, phần 'Điều này nhận được hầu hết các định dạng' của câu trả lời. :)
Alex Stephens

4

Quy tắc cơ bản:

^[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9][ABD-HJLNP-UW-Z]{2}$

Mã bưu chính ở Anh (hoặc mã bưu điện, như chúng được gọi) bao gồm năm đến bảy ký tự chữ và số được phân tách bằng khoảng trắng. Các quy tắc bao gồm các nhân vật có thể xuất hiện tại các vị trí cụ thể là khá phức tạp và có nhiều ngoại lệ. Do đó, biểu thức chính quy chỉ hiển thị theo các quy tắc cơ bản.

Hoàn thành quy tắc:

Nếu bạn cần một regex đánh dấu vào tất cả các ô cho các quy tắc mã bưu điện với chi phí dễ đọc, thì bạn vào đây:

^(?:(?:[A-PR-UWYZ][0-9]{1,2}|[A-PR-UWYZ][A-HK-Y][0-9]{1,2}|[A-PR-UWYZ][0-9][A-HJKSTUW]|[A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRV-Y]) [0-9][ABD-HJLNP-UW-Z]{2}|GIR 0AA)$

Nguồn: https://www.safaribooksonline.com

Đã thử nghiệm đối với cơ sở dữ liệu khách hàng của chúng tôi và có vẻ hoàn toàn chính xác.


4

Tôi sử dụng regex sau đây mà tôi đã thử nghiệm đối với tất cả các mã bưu điện hợp lệ của Vương quốc Anh. Nó dựa trên các quy tắc được đề xuất, nhưng cô đọng càng nhiều càng hợp lý và không sử dụng bất kỳ quy tắc regex cụ thể nào về ngôn ngữ.

([A-PR-UWYZ]([A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y])?|[0-9]([0-9]|[A-HJKPSTUW])?) ?[0-9][ABD-HJLNP-UW-Z]{2})

Nó giả định rằng mã bưu điện đã được chuyển đổi thành chữ hoa và không có ký tự dẫn hoặc dấu, nhưng sẽ chấp nhận một khoảng trắng tùy chọn giữa mã ngoài và mã hóa.

Mã bưu điện "GIR0 0AA" đặc biệt bị loại trừ và sẽ không xác thực vì nó không có trong danh sách mã bưu chính chính thức và theo như tôi biết sẽ không được sử dụng làm địa chỉ đã đăng ký. Thêm nó nên tầm thường như một trường hợp đặc biệt nếu được yêu cầu.


4

Tôi muốn một regex đơn giản, nơi cho phép quá nhiều, nhưng không từ chối một mã bưu điện hợp lệ. Tôi đã đi với điều này (đầu vào là một chuỗi bị tước / cắt):

/^([a-z0-9]\s*){5,8}$/i

Điều này cho phép các mã bưu điện ngắn nhất có thể như "L1 8JQ" cũng như các mã dài nhất như "OL14 5ET".

Bởi vì nó cho phép tối đa 8 ký tự, nó cũng sẽ cho phép mã bưu điện 8 ký tự không chính xác nếu không có khoảng trắng: "OL145ETX". Nhưng một lần nữa, đây là một regex đơn giản, vì khi đó là đủ tốt.


Ồ, lời xin lỗi của tôi. Tôi nghĩ rằng tôi đã bỏ lỡ / i khi tôi đã thử nghiệm ngày hôm qua.
Giăng

3

Nửa đầu của mã bưu điện Các định dạng hợp lệ

  • [AZ] [AZ] [0-9] [AZ]
  • [AZ] [AZ] [0-9] [0-9]
  • [AZ] [0-9] [0-9]
  • [AZ] [AZ] [0-9]
  • [AZ] [AZ] [AZ]
  • [AZ] [0-9] [AZ]
  • [AZ] [0-9]

Ngoại lệ
Vị trí 1 - QVX không được sử dụng
Vị trí 2 - IJZ không được sử dụng ngoại trừ ở GIR 0AA
Vị trí 3 - AEHMNPRTVXY chỉ được sử dụng
Vị trí 4 - ABEHMNPRVWXY

Nửa sau của mã bưu điện

  • [0-9] [AZ] [AZ]

Ngoại lệ
Vị trí 2 + 3 - CIKMOV không được sử dụng

Hãy nhớ rằng không phải tất cả các mã có thể được sử dụng, vì vậy danh sách này là điều kiện cần nhưng không đủ cho một mã hợp lệ. Có thể dễ dàng hơn để chỉ phù hợp với một danh sách tất cả các mã hợp lệ?


3

Để kiểm tra mã bưu điện có ở định dạng hợp lệ theo hướng dẫn của lập trình viên của Royal Mail :

          |----------------------------outward code------------------------------| |------inward code-----|
#special↓       α1        α2    AAN  AANA      AANN      AN    ANN    ANA (α3)        N         AA
^(GIR 0AA|[A-PR-UWYZ]([A-HK-Y]([0-9][A-Z]?|[1-9][0-9])|[1-9]([0-9]|[A-HJKPSTUW])?) [0-9][ABD-HJLNP-UW-Z]{2})$

Tất cả các mã bưu điện trên doogal.co.uk phù hợp, ngoại trừ những mã không còn được sử dụng.

Thêm dấu cách ?sau dấu cách và sử dụng kết hợp không phân biệt chữ hoa chữ thường để trả lời câu hỏi này:

'se50eg'.match(/^(GIR 0AA|[A-PR-UWYZ]([A-HK-Y]([0-9][A-Z]?|[1-9][0-9])|[1-9]([0-9]|[A-HJKPSTUW])?) ?[0-9][ABD-HJLNP-UW-Z]{2})$/ig);
Array [ "se50eg" ]

3

Điều này cho phép các không gian trống và các tab từ cả hai phía trong trường hợp bạn không muốn xác nhận thất bại và sau đó cắt bớt bên đó.

^\s*(([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) {0,1}[0-9][A-Za-z]{2})\s*$)

Đây là mẫu duy nhất hoạt động với tôi bằng c # (System.Text.RegularExpressions) với các ví dụ được mô tả trong câu hỏi ban đầu
MattjeS

Đây là regex bị hỏng của chính phủ Anh và nó không thể xác nhận một số định dạng hợp lệ.
ctwheels

@ctwheels Xin chào, bạn có thể vui lòng cung cấp mã bưu điện không, cảm ơn.
Matas Vaitkevicius

Ví dụ: AAA 1AAkhông phải là một định dạng hợp lệ: xem câu trả lời của tôi để được giải thích và khắc phục.
ctwheels

2

Để thêm vào danh sách này một regex thực tế hơn mà tôi sử dụng cho phép người dùng nhập vào empty stringlà:

^$|^(([gG][iI][rR] {0,}0[aA]{2})|((([a-pr-uwyzA-PR-UWYZ][a-hk-yA-HK-Y]?[0-9][0-9]?)|(([a-pr-uwyzA-PR-UWYZ][0-9][a-hjkstuwA-HJKSTUW])|([a-pr-uwyzA-PR-UWYZ][a-hk-yA-HK-Y][0-9][abehmnprv-yABEHMNPRV-Y]))) {0,1}[0-9][abd-hjlnp-uw-zABD-HJLNP-UW-Z]{2}))$

Regex này cho phép viết hoa và viết thường với một khoảng trắng tùy chọn ở giữa

Từ quan điểm của các nhà phát triển phần mềm, regex này rất hữu ích cho phần mềm trong đó địa chỉ có thể là tùy chọn. Ví dụ: nếu người dùng không muốn cung cấp chi tiết địa chỉ của họ


1

Hãy xem mã python trên trang này:

http://www.brastyonline.net/simon/blog/archives/001292.html

Tôi đã có một số phân tích mã bưu điện để làm. Yêu cầu khá đơn giản; Tôi phải phân tích một mã bưu điện thành một mã ngoài và mã hóa (tùy chọn). Điểm mới là tôi không phải thực hiện bất kỳ xác nhận nào - tôi chỉ cần xử lý những gì tôi đã được cung cấp một cách thông minh mơ hồ. Tôi không thể giả định nhiều về nhập khẩu của tôi về định dạng, ví dụ như trường hợp và không gian nhúng. Nhưng đây không phải là tin xấu; Tin xấu là tôi phải làm tất cả trong RPG. :-(

Tuy nhiên, tôi đã ném một hàm Python nhỏ lại với nhau để làm rõ suy nghĩ của mình.

Tôi đã sử dụng nó để xử lý mã bưu điện cho tôi.


1

Chúng tôi đã đưa ra một thông số:

Mã bưu điện của Vương quốc Anh phải ở một trong các hình thức sau (với một ngoại lệ, xem bên dưới): 
    § A9 9AA 
    § A99 9AA
    § AA9 9AA
    § AA99 9AA
    § A9A 9AA
    § AA9A 9AA
Trong đó A đại diện cho một ký tự chữ cái và 9 đại diện cho một ký tự số.
Các quy tắc bổ sung áp dụng cho các ký tự chữ cái, như sau:
    § Ký tự ở vị trí 1 có thể không phải là Q, V hoặc X
    § Nhân vật ở vị trí 2 có thể không phải là I, J hoặc Z
    § Ký tự ở vị trí 3 có thể không phải là I, L, M, N, O, P, Q, R, V, X, Y hoặc Z
    § Ký tự ở vị trí 4 có thể không phải là C, D, F, G, I, J, K, L, O, Q, S, T, U hoặc Z
    § Các ký tự ở hai vị trí ngoài cùng bên phải có thể không phải là C, I, K, M, O hoặc V
Một ngoại lệ không tuân theo các quy tắc chung này là mã bưu điện "GIR 0AA", đây là một mã bưu điện hợp lệ đặc biệt.

Chúng tôi đã đưa ra điều này:

/^([A-PR-UWYZ][A-HK-Y0-9](?:[A-HJKS-UW0-9][ABEHMNPRV-Y0-9]?)?\s*[0-9][ABD-HJLNP-UW-Z]{2}|GIR\s*0AA)$/i

Nhưng lưu ý - điều này cho phép bất kỳ số lượng không gian ở giữa các nhóm.


2
paulslater19, thật không may, giải pháp của bạn cho phép mã hóa A99A 9AA.

1

Tôi có regex để xác thực Mã bưu chính của Anh.

Điều này đang làm việc cho tất cả các loại Mã bưu điện bên trong hoặc bên ngoài

^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))) || ^((GIR)[ ]?(0AA))$|^(([A-PR-UWYZ][0-9])[ ]?([0-9][ABD-HJLNPQ-UW-Z]{0,2}))$|^(([A-PR-UWYZ][0-9][0-9])[ ]?([0-9][ABD-HJLNPQ-UW-Z]{0,2}))$|^(([A-PR-UWYZ][A-HK-Y0-9][0-9])[ ]?([0-9][ABD-HJLNPQ-UW-Z]{0,2}))$|^(([A-PR-UWYZ][A-HK-Y0-9][0-9][0-9])[ ]?([0-9][ABD-HJLNPQ-UW-Z]{0,2}))$|^(([A-PR-UWYZ][0-9][A-HJKS-UW0-9])[ ]?([0-9][ABD-HJLNPQ-UW-Z]{0,2}))$|^(([A-PR-UWYZ][A-HK-Y0-9][0-9][ABEHMNPRVWXY0-9])[ ]?([0-9][ABD-HJLNPQ-UW-Z]{0,2}))$

Điều này đang làm việc cho tất cả các loại định dạng.

Thí dụ:

AB10 --------------------> CHỈ SAU POSTCODE

A1 1AA ------------------> KẾT HỢP (NGOÀI VÀ BÊN TRONG) POSTCODE

WC2A --------------------> NGOÀI


1

Câu trả lời được chấp nhận phản ánh các quy tắc được đưa ra bởi Royal Mail, mặc dù có một lỗi đánh máy trong regex. Lỗi đánh máy này dường như cũng đã có trên trang web gov.uk (vì nó nằm trong trang lưu trữ XML).

Trong định dạng A9A 9AA, các quy tắc cho phép một ký tự P ở vị trí thứ ba, trong khi regex không cho phép điều này. Regex chính xác sẽ là:

(GIR 0AA)|((([A-Z-[QVX]][0-9][0-9]?)|(([A-Z-[QVX]][A-Z-[IJZ]][0-9][0-9]?)|(([A-Z-[QVX]][0-9][A-HJKPSTUW])|([A-Z-[QVX]][A-Z-[IJZ]][0-9][ABEHMNPRVWXY])))) [0-9][A-Z-[CIKMOV]]{2}) 

Rút ngắn kết quả này trong regex sau (sử dụng cú pháp Perl / Ruby):

(GIR 0AA)|([A-PR-UWYZ](([0-9]([0-9A-HJKPSTUW])?)|([A-HK-Y][0-9]([0-9ABEHMNPRVWXY])?))\s?[0-9][ABD-HJLNP-UW-Z]{2})

Nó cũng bao gồm một không gian tùy chọn giữa khối thứ nhất và thứ hai.


1

Những gì tôi đã tìm thấy trong gần như tất cả các biến thể và regex từ pdf chuyển số lượng lớn và trên trang wikipedia là gì, đặc biệt đối với regex wikipedia, cần phải có một ^ sau thanh đầu tiên (thanh dọc). Tôi đã tìm ra điều này bằng cách thử nghiệm cho AA9A 9AA, bởi vì nếu không thì việc kiểm tra định dạng cho A9A 9AA sẽ xác nhận nó. Ví dụ, việc kiểm tra EC1D 1BB không hợp lệ sẽ trở lại hợp lệ vì C1D 1BB là định dạng hợp lệ.

Đây là những gì tôi đã đưa ra cho một regex tốt:

^([G][I][R] 0[A]{2})|^((([A-Z-[QVX]][0-9]{1,2})|([A-Z-[QVX]][A-HK-Y][0-9]{1,2})|([A-Z-[QVX]][0-9][ABCDEFGHJKPSTUW])|([A-Z-[QVX]][A-HK-Y][0-9][ABEHMNPRVWXY])) [0-9][A-Z-[CIKMOV]]{2})$

1

Thông qua kiểm tra và quan sát thực nghiệm, cũng như xác nhận với https://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom#Validation , đây là phiên bản regex Python của tôi phân tích chính xác và xác thực mã bưu chính của Anh:

UK_POSTCODE_REGEX = r'(?P<postcode_area>[A-Z]{1,2})(?P<district>(?:[0-9]{1,2})|(?:[0-9][A-Z]))(?P<sector>[0-9])(?P<postcode>[A-Z]{2})'

Regex này là đơn giản và có các nhóm chụp. Nó không bao gồm tất cả các xác nhận của mã bưu chính hợp pháp của Vương quốc Anh, mà chỉ tính đến chữ cái và vị trí số.

Đây là cách tôi sẽ sử dụng nó trong mã:

@dataclass
class UKPostcode:
    postcode_area: str
    district: str
    sector: int
    postcode: str

    # https://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom#Validation
    # Original author of this regex: @jontsai
    # NOTE TO FUTURE DEVELOPER:
    # Verified through empirical testing and observation, as well as confirming with the Wiki article
    # If this regex fails to capture all valid UK postcodes, then I apologize, for I am only human.
    UK_POSTCODE_REGEX = r'(?P<postcode_area>[A-Z]{1,2})(?P<district>(?:[0-9]{1,2})|(?:[0-9][A-Z]))(?P<sector>[0-9])(?P<postcode>[A-Z]{2})'

    @classmethod
    def from_postcode(cls, postcode):
        """Parses a string into a UKPostcode

        Returns a UKPostcode or None
        """
        m = re.match(cls.UK_POSTCODE_REGEX, postcode.replace(' ', ''))

        if m:
            uk_postcode = UKPostcode(
                postcode_area=m.group('postcode_area'),
                district=m.group('district'),
                sector=m.group('sector'),
                postcode=m.group('postcode')
            )
        else:
            uk_postcode = None

        return uk_postcode


def parse_uk_postcode(postcode):
    """Wrapper for UKPostcode.from_postcode
    """
    uk_postcode = UKPostcode.from_postcode(postcode)
    return uk_postcode

Dưới đây là các bài kiểm tra đơn vị:

@pytest.mark.parametrize(
    'postcode, expected', [
        # https://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom#Validation
        (
            'EC1A1BB',
            UKPostcode(
                postcode_area='EC',
                district='1A',
                sector='1',
                postcode='BB'
            ),
        ),
        (
            'W1A0AX',
            UKPostcode(
                postcode_area='W',
                district='1A',
                sector='0',
                postcode='AX'
            ),
        ),
        (
            'M11AE',
            UKPostcode(
                postcode_area='M',
                district='1',
                sector='1',
                postcode='AE'
            ),
        ),
        (
            'B338TH',
            UKPostcode(
                postcode_area='B',
                district='33',
                sector='8',
                postcode='TH'
            )
        ),
        (
            'CR26XH',
            UKPostcode(
                postcode_area='CR',
                district='2',
                sector='6',
                postcode='XH'
            )
        ),
        (
            'DN551PT',
            UKPostcode(
                postcode_area='DN',
                district='55',
                sector='1',
                postcode='PT'
            )
        )
    ]
)
def test_parse_uk_postcode(postcode, expected):
    uk_postcode = parse_uk_postcode(postcode)
    assert(uk_postcode == expected)

0

Tôi cần một phiên bản sẽ hoạt động trong SAS với các PRXMATCHchức năng và có liên quan, vì vậy tôi đã nghĩ ra điều này:

^[A-PR-UWYZ](([A-HK-Y]?\d\d?)|(\d[A-HJKPSTUW])|([A-HK-Y]\d[ABEHMNPRV-Y]))\s?\d[ABD-HJLNP-UW-Z]{2}$

Các trường hợp thử nghiệm và ghi chú:

/* 
Notes
The letters QVX are not used in the 1st position.
The letters IJZ are not used in the second position.
The only letters to appear in the third position are ABCDEFGHJKPSTUW when the structure starts with A9A.
The only letters to appear in the fourth position are ABEHMNPRVWXY when the structure starts with AA9A.
The final two letters do not use the letters CIKMOV, so as not to resemble digits or each other when hand-written.
*/

/*
    Bits and pieces
    1st position (any):         [A-PR-UWYZ]         
    2nd position (if letter):   [A-HK-Y]
    3rd position (A1A format):  [A-HJKPSTUW]
    4th position (AA1A format): [ABEHMNPRV-Y]
    Last 2 positions:           [ABD-HJLNP-UW-Z]    
*/


data example;
infile cards truncover;
input valid 1. postcode &$10. Notes &$100.;
flag = prxmatch('/^[A-PR-UWYZ](([A-HK-Y]?\d\d?)|(\d[A-HJKPSTUW])|([A-HK-Y]\d[ABEHMNPRV-Y]))\s?\d[ABD-HJLNP-UW-Z]{2}$/',strip(postcode));
cards;
1  EC1A 1BB  Special case 1
1  W1A 0AX   Special case 2
1  M1 1AE    Standard format
1  B33 8TH   Standard format
1  CR2 6XH   Standard format
1  DN55 1PT  Standard format
0  QN55 1PT  Bad letter in 1st position
0  DI55 1PT  Bad letter in 2nd position
0  W1Z 0AX   Bad letter in 3rd position
0  EC1Z 1BB  Bad letter in 4th position
0  DN55 1CT  Bad letter in 2nd group
0  A11A 1AA  Invalid digits in 1st group
0  AA11A 1AA  1st group too long
0  AA11 1AAA  2nd group too long
0  AA11 1AAA  2nd group too long
0  AAA 1AA   No digit in 1st group
0  AA 1AA    No digit in 1st group
0  A 1AA     No digit in 1st group
0  1A 1AA    Missing letter in 1st group
0  1 1AA     Missing letter in 1st group
0  11 1AA    Missing letter in 1st group
0  AA1 1A    Missing letter in 2nd group
0  AA1 1     Missing letter in 2nd group
;
run;

0

Phương pháp dưới đây sẽ kiểm tra mã bài và cung cấp thông tin đầy đủ

const valid_postcode = postcode => {
    try {
        postcode = postcode.replace(/\s/g, "");
        const fromat = postcode
            .toUpperCase()
            .match(/^([A-Z]{1,2}\d{1,2}[A-Z]?)\s*(\d[A-Z]{2})$/);
        const finalValue = `${fromat[1]} ${fromat[2]}`;
        const regex = /^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z]))))[0-9][A-Za-z]{2})$/i;
        return {
            isValid: regex.test(postcode),
            formatedPostCode: finalValue,
            error: false,
            info: 'It is a valid postcode'
        };
    } catch (error) {
        return { error: true , info: 'Invalid post code has been entered!'};
    }
};
valid_postcode('GU348RR')
result => {isValid: true, formatedPostCode: "GU34 8RR", error: false, info: "It is a valid postcode"}
valid_postcode('sdasd4746asd')
result => {error: true, info: "Invalid post code has been entered!"}
valid_postcode('787898523')
result => {error: true, info: "Invalid post code has been entered!"}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.