RegEx dla pasujących kodów pocztowych w Wielkiej Brytanii

186

Jestem po wyrażeniu regularnym, które zweryfikuje pełny złożony kod pocztowy w Wielkiej Brytanii tylko w ciągu wejściowym. Wszystkie nietypowe formularze kodów pocztowych muszą być objęte, tak jak zwykle. Na przykład:

mecze

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

Nie pasuje

  • aWC2H 7LT
  • WC2H 7LTa
  • WC2H

Jak rozwiązać ten problem?

Kieran Benton
źródło
2
@axrwkr, który nie wygląda na pomocny
Kieran Benton,
8
Sprawdzanie poprawności kodów pocztowych w Wielkiej Brytanii - JavaScript i PHP Nie mogłem uzyskać akceptowanej odpowiedzi w celu dopasowania prawidłowych kodów pocztowych, ale znalazłem to i pasuje ona do prawidłowych kodów pocztowych. W przypadku sprawdzania poprawności po stronie klienta można używać wersji JavaScript bez zmian, w przypadku sprawdzania poprawności po stronie serwera przepisywanie kodu JavaScript, ponieważ C # jest dość proste. Sformatuje nawet kod pocztowy, aby zawierał spację, więc jeśli wpiszesz kod pocztowy jako W1A1AA, oprócz sprawdzania poprawności, sformatuje go do W1A 1AA. Zajmuje się nawet nietypowymi kodami pocztowymi na różnych terytoriach brytyjskich.
2
Podany link nie działa w przypadku formatów „AA1A 1AA”. Odniesienie: dhl.com.tw/content/dam/downloads/tw/express/forms/…
Anthony Scaife
1
Jeśli chcesz po prostu zweryfikować kod pocztowy, oferujemy bezpłatny (wymagana rejestracja) punkt końcowy REST API do sprawdzania poprawności - developers.alliescomputing.com/postcoder-web-api/address-lookup/...
Stephen Keable
1
Dobre pytanie. Myślę, że warto umieścić centralne kody pocztowe Manchesteru, takie jak „M1 3HZ”, na liście rzadkich przykładów, które muszą pasować. Wiele osób nie zdaje sobie sprawy z kombinacji 1-literowej liczby.
Martin Joiner,

Odpowiedzi:

208

Polecam zapoznać się z brytyjskim standardem danych rządowych dla kodów pocztowych [link już nie żyje; archiwum XML , dyskusja w Wikipedii ]. Istnieje krótki opis danych, a dołączony schemat xml zawiera wyrażenie regularne. To może nie być dokładnie to, czego chcesz, ale byłby dobrym punktem wyjścia. RegEx różni się nieco od XML, ponieważ znak P na trzeciej pozycji w formacie A9A 9AA jest dozwolony przez podaną definicję.

RegEx dostarczone przez rząd Wielkiej Brytanii to:

([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})

Jak wskazano w dyskusji na Wikipedii, pozwoli to na użycie niektórych nierzeczywistych kodów pocztowych (np. Zaczynających AA, ZY) i zapewni bardziej rygorystyczny test, który możesz wypróbować.

Brian Campbell
źródło
52
I ten reg np. Z opcjonalną białą spacją między dwoma segmentami (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
7
Może to być dobry pomysł, aby uzyskać odpowiedź na wyrażenie regularne, ponieważ strony wydają się wygasać co roku ...
pauloya
7
Zauważ, że to wyrażenie regularne dotyczy schematu XML, który oczywiście różni się nieco od innych smaków
wyrażeń
6
Nie mogę tego uruchomić w JavaScript. Czy działa tylko z niektórymi silnikami wyrażeń regularnych?
NickG
12
Właściwie to zmienili: Przesyłanie danych zbiorczych :^([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

Wygląda na to, że będziemy używać ^(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})$ , czyli nieco zmodyfikowanej wersji sugestii Minglis powyżej.

Będziemy jednak musieli dokładnie zbadać, jakie są reguły, ponieważ wydaje się, że różne rozwiązania wymienione powyżej stosują różne reguły dotyczące dozwolonych liter.

Po kilku badaniach znaleźliśmy więcej informacji. Wygląda na to, że strona „govtalk.gov.uk” wskazuje ci kod pocztowy govtalk-postcode . Wskazuje to na schemat XML w schemacie XML, który zawiera instrukcję „pseudo regex” reguł kodu pocztowego.

Podjęliśmy to i pracowaliśmy nad tym, aby dać nam następujące wyrażenie:

^((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}))$

To sprawia, że ​​spacje są opcjonalne, ale ogranicza Cię do jednego spacji (zamień „&” na „{0,} dla nieograniczonej liczby spacji). Zakłada, że ​​cały tekst musi być pisany wielkimi literami.

Jeśli chcesz zezwolić na małe litery, z dowolną liczbą spacji, użyj:

^(([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}))$

Nie obejmuje to terytoriów zamorskich i wymusza jedynie format, a NIE istnienie różnych obszarów. Opiera się na następujących zasadach:

Może akceptować następujące formaty:

  • „GIR 0AA”
  • A9 9ZZ
  • A99 9ZZ
  • AB9 9ZZ
  • AB99 9ZZ
  • A9C 9ZZ
  • AD9E 9ZZ

Gdzie:

  • 9 może być dowolnym numerem jednocyfrowym.
  • A może być dowolną literą oprócz Q, V lub X.
  • B może być dowolną literą oprócz I, J lub Z.
  • C może być dowolną literą oprócz I, L, M, N, O, P, Q, R, V, X, Y lub Z.
  • D może być dowolną literą oprócz I, J lub Z.
  • E może być dowolnym spośród A, B, E, H, M, N, P, R, V, W, X lub Y.
  • Z może być dowolną literą oprócz C, I, K, M, O lub V.

Wszystkiego najlepszego

Colin

Colin
źródło
2
Świetna odpowiedź, dodałem za granicą^(([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,
Po co określać {0,}zamiast *nieograniczonej liczby opcjonalnych miejsc?
Code Animal
76

Niedawno pisał odpowiedź na to pytanie na temat kodów pocztowych Wielkiej Brytanii na języku R . Odkryłem, że wzorzec wyrażenia regularnego rządu brytyjskiego jest nieprawidłowy i nie działa prawidłowo zweryfikować niektóre kody pocztowe. Niestety wiele odpowiedzi tutaj opiera się na tym niepoprawnym wzorze.

Poniżej opiszę niektóre z tych problemów i przedstawię poprawione wyrażenie regularne, które faktycznie działa.


Uwaga

Moja odpowiedź (i ogólnie wyrażenia regularne):

  • Sprawdza tylko formaty kodów pocztowych .
  • Nie zapewnia legalności istnienia kodu pocztowego .
    • W tym celu użyj odpowiedniego interfejsu API! Zobacz odpowiedź Bena, aby uzyskać więcej informacji.

Jeśli nie zależy ci na złym wyrażeniu regularnym i po prostu chcesz przejść do odpowiedzi, przewiń w dół do odpowiedzi sekcji .

The Bad Regex

Nie należy używać wyrażeń regularnych w tej sekcji.

Jest to błąd polegający na tym, że rząd Wielkiej Brytanii dostarczył programistom (nie jestem pewien, jak długo będzie działał ten link, ale można to zobaczyć w dokumentacji Bulk Data Transfer ):

^([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})$

Problemy

Problem 1 - Kopiuj / Wklej

Zobacz regex w użyciu tutaj .

Jak zapewne wielu programistów, kopiuje / wkleja kod (szczególnie wyrażenia regularne) i wkleja, oczekując, że zadziałają. Chociaż jest to świetne w teorii, nie udaje się w tym konkretnym przypadku, ponieważ kopiowanie / wklejanie z tego dokumentu faktycznie zmienia jeden ze znaków (spację) na znak nowej linii, jak pokazano poniżej:

^([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})$

Pierwszą rzeczą, którą zrobią większość programistów, jest po prostu usunięcie nowej linii bez zastanowienia się. Teraz wyrażenie regularne nie będzie pasowało do kodów pocztowych ze spacjami w nich (innymi niżGIR 0AA kod pocztowy).

Aby rozwiązać ten problem, znak nowej linii należy zastąpić znakiem spacji:

^([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})$
                                                                                                                                                     ^

Problem 2 - Granice

Zobacz regex w użyciu tutaj .

^([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})$
^^                     ^ ^                                                                                                                                            ^^

Wyrażenie kodu pocztowego nieprawidłowo zakotwicza wyrażenie regularne. Każdy, kto używa tego wyrażenia regularnego do sprawdzania kodów pocztowych, może być zaskoczony, jeśli wartość taka jakfooA11 1AA . Jest tak, ponieważ zakotwiczili początek pierwszej opcji i koniec drugiej opcji (niezależnie od siebie), jak wskazano w wyrażeniu regularnym powyżej.

Oznacza to, że ^(zapewnia pozycję na początku wiersza) działa tylko w pierwszej opcji ([Gg][Ii][Rr] 0[Aa]{2}), więc druga opcja zweryfikuje wszystkie ciągi, które się kończą się kodem pocztowym (niezależnie od tego, co nastąpi wcześniej).

Podobnie pierwsza opcja nie jest zakotwiczona na końcu linii $, więc GIR 0AAfoojest również akceptowana.

^([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})$

Aby rozwiązać ten problem, obie opcje należy zapakować w inną grupę (lub grupę nieprzechwycącą), a kotwice umieścić wokół tego:

^(([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}))$
^^                                                                                                                                                                      ^^

Problem 3 - Niewłaściwy zestaw znaków

Zobacz regex w użyciu tutaj .

^([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})$
                                                                                       ^^

Wyrażenie regularne brakuje -tutaj, aby wskazać zakres znaków. W obecnej postaci, jeśli kod pocztowy ma format ANA NAA(gdzie Areprezentuje literę i Ncyfrę) i zaczyna się od czegoś innego niż AlubZ , nie powiedzie się.

Oznacza to, że będzie on pasował A1A 1AAi Z1A 1AA, ale nie B1A 1AA.

Aby rozwiązać ten problem, znak -należy umieścić między Aoraz Zw odpowiednim zestawie znaków:

^([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})$
                                                                                        ^

Problem 4 - Niepoprawny opcjonalny zestaw znaków

Zobacz regex w użyciu tutaj .

^([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})$
                                                                                                                                        ^

Przysięgam, że nawet nie przetestowali tego przed opublikowaniem go w Internecie. Zrobili opcjonalny niewłaściwy zestaw znaków. Dokonali [0-9]opcji w czwartym podwariacie opcji 2 (grupa 9). Dzięki temu wyrażenie regularne dopasowuje niepoprawnie sformatowane kody pocztowe, takie jakAAA 1AA .

Aby rozwiązać ten problem, ustaw opcjonalną następną klasę znaków (a następnie [0-9]dopasuj zestaw dokładnie raz):

^([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})$
                                                                                                                                                ^

Problem 5 - Wydajność

Wydajność tego wyrażenia regularnego jest bardzo niska. Po pierwsze, umieścili najmniej prawdopodobną opcję dopasowania GIR 0AAna początku. Ilu użytkowników prawdopodobnie będzie miało ten kod pocztowy w porównaniu do dowolnego innego kodu pocztowego; prawdopodobnie nigdy? Oznacza to, że przy każdym użyciu wyrażenia regularnego musi on wyczerpać tę opcję przed przejściem do następnej opcji. Aby zobaczyć, jak wpływa to na wydajność, sprawdź liczbę kroków, które wykonał pierwotny regex (35) w stosunku do tego samego regex po odwróceniu opcji (22).

Drugi problem z wydajnością wynika ze struktury całego wyrażenia regularnego. Nie ma sensu cofanie się po każdej opcji, jeśli jedna zawiedzie. Strukturę obecnego wyrażenia regularnego można znacznie uprościć. Podaję poprawkę w sekcji Odpowiedź .

Problem 6 - Przestrzenie

Zobacz regex w użyciu tutaj

Nie może to być uważane za problem , ale budzi zaniepokojenie większości programistów. Spacje w wyrażeniu regularnym nie są opcjonalne, co oznacza, że ​​użytkownicy wprowadzający swoje kody pocztowe muszą umieścić spację w kodzie pocztowym. Jest to łatwa poprawka, po prostu dodając ?spacje, aby uczynić je opcjonalnymi. Aby uzyskać poprawkę, zobacz sekcję Odpowiedź .


Odpowiedź

1. Ustalenie Regeksu rządu Wielkiej Brytanii

Naprawienie wszystkich problemów opisanych w sekcji Problemy i uproszczenie wzoru daje następujący, krótszy i bardziej zwięzły wzór. Możemy również usunąć większość grup, ponieważ weryfikujemy kod pocztowy jako całość (nie poszczególne części):

Zobacz regex w użyciu tutaj

^([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})$

Można to dodatkowo skrócić, usuwając wszystkie zakresy z jednego ze znaków (wielkie lub małe) i używając flagi bez rozróżniania wielkości liter. Uwaga : niektóre języki nie mają takiego, więc użyj dłuższego z powyższych. Każdy język implementuje flagę rozróżniania wielkości liter inaczej.

Zobacz regex w użyciu tutaj .

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

Krótszy ponownie wymianie [0-9]z \d(jeśli silnik regex je obsługuje):

Zobacz regex w użyciu tutaj .

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

2. Uproszczone wzory

Bez konieczności podawania określonych znaków alfabetycznych można użyć następujących (pamiętaj o uproszczeniach z 1. Ustalono również tutaj Regex Rządu Zjednoczonego Królestwa ):

Zobacz regex w użyciu tutaj .

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

Co więcej, jeśli nie zależy ci na specjalnym przypadku GIR 0AA:

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

3. Skomplikowane wzory

Nie sugeruję nadmiernej weryfikacji kodu pocztowego, ponieważ nowe Obszary, Dzielnice i Podrejgi mogą pojawić się w dowolnym momencie. To, co zasugeruję potencjalnie do zrobienia, to dodane wsparcie dla przypadków skrajnych. Istnieją specjalne przypadki, które opisano w tym artykule w Wikipedii .

Oto złożone wyrażenia regularne, które zawierają podrozdziały 3. (3.1, 3.2, 3.3).

W odniesieniu do wzorców w 1. Naprawianie Regeksu rządu Wielkiej Brytanii :

Zobacz regex w użyciu tutaj

^(([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)$

I w związku z 2. Uproszczonymi wzorami :

Zobacz regex w użyciu tutaj

^(([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 Brytyjskie terytoria zamorskie

Artykuł w Wikipedii stwierdza obecnie (niektóre formaty nieco uproszczone):

  • AI-1111: Anguila
  • ASCN 1ZZ: Wyspa Wniebowstąpienia
  • STHL 1ZZ: Święta Helena
  • TDCU 1ZZ: Tristan da Cunha
  • BBND 1ZZ: Brytyjskie Terytorium Oceanu Indyjskiego
  • BIQQ 1ZZ: Brytyjskie Terytorium Antarktyczne
  • FIQQ 1ZZ: Falklandy
  • GX11 1ZZ: Gibraltar
  • PCRN 1ZZ: Wyspy Pitcairn
  • SIQQ 1ZZ: Georgia Południowa i Sandwich Południowy
  • TKCA 1ZZ: Wyspy Turks i Caicos
  • BFPO 11: Akrotiri i Dhekelia
  • ZZ 11I GE CX: Bermudy (zgodnie z tym dokumentem )
  • KY1-1111: Kajmany (zgodnie z tym dokumentem )
  • VG1111: Brytyjskie Wyspy Dziewicze (zgodnie z tym dokumentem )
  • MSR 1111: Montserrat (zgodnie z tym dokumentem )

Kompleksowy regex pasujący tylko do brytyjskich terytoriów zamorskich może wyglądać następująco:

Zobacz regex w użyciu tutaj .

^((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 Urząd pocztowy sił brytyjskich

Chociaż zostały ostatnio zmienione, aby lepiej dostosować się do brytyjskiego systemu kodów pocztowych do BF#(gdzie #reprezentuje liczbę), są uważane za opcjonalne alternatywne kody pocztowe . Te kody pocztowe mają (ed) format BFPO, a następnie 1-4 cyfry:

Zobacz regex w użyciu tutaj

^BFPO ?\d{1,4}$

3.3 Święty Mikołaj?

Mikołaj ma inny szczególny przypadek (jak wspomniano w innych odpowiedziach): SAN TA1jest to prawidłowy kod pocztowy. Wyrażenie regularne tego jest bardzo proste:

^SAN ?TA1$
ctwheels
źródło
4
Uproszczone wzory to naprawdę dobra opcja do użycia. Uważam, że najlepiej nie ograniczać wyrażenia regularnego, ponieważ musisz upewnić się, że jest on aktualizowany przy użyciu jakichkolwiek zmian lub możesz mieć bardzo wściekłych użytkowników. Uważam, że lepiej jest luźniej dopasować za pomocą uproszczonego wyrażenia regularnego, aby wyeliminować oczywiste błędy, a następnie zastosować dalsze kontrole, takie jak wyszukiwanie adresu (lub wiadomość e-mail z potwierdzeniem w przypadku wyrażenia regularnego), aby potwierdzić ważność.
James Coyle
2
Doskonała i dokładna analiza.
Steve
1
Genialna odpowiedź na tak wielu poziomach. Ostatecznie wybrałem twój drugi uproszczony wzór. Ponieważ faktycznie mam DB z wszystkimi kodami pocztowymi w Wielkiej Brytanii, potrzebuję tylko pierwszego przejścia, aby sprawdzić, czy ciąg adresu potencjalnie zawiera prawidłowy kod pocztowy, więc nie dbam o fałszywe alarmy (ponieważ rzeczywiste wyszukiwanie je wykończy) , ale dbam o fałszywe negatywy. Ważna jest także prędkość.
John Powell,
Jest tak wiele problemów z brytyjskim systemem kodów pocztowych, które zostały stworzone przez komitet przed erą komputerów, ale kwestia zmiennej długości i odstępów jest jednym z najbardziej szkodliwych. Widziałem wszystkie rodzaje horrorów, w tym kody pocztowe wypełniające, takie jak E1 5JX do E1 5JX, tj. Z trzema spacjami, aby dobrze pasowało do SW18 5HA w Excelu (wstaw strasznie nieodpowiednie oprogramowanie do zarządzania adresami). Jedynym rozsądnym rozwiązaniem, IMHO, jest usunięcie wszystkich spacji, aby kod pocztowy był jednym ciągiem, zanim znajdzie się w pobliżu Elastic, Solr, Postgres itp.
John Powell,
45

Nie ma czegoś takiego jak kompleksowe wyrażenie regularne kodów pocztowych w Wielkiej Brytanii, które jest w stanie zweryfikować kod pocztowy. Możesz sprawdzić, czy kod pocztowy ma poprawny format, używając wyrażenia regularnego; nie że tak naprawdę istnieje.

Kody pocztowe są dowolnie złożone i ciągle się zmieniają. Na przykład kod pocztowy W1nie ma i może nigdy nie mieć wszystkich liczb od 1 do 99 dla każdego obszaru kodu pocztowego.

Nie możesz oczekiwać, że to, co obecnie istnieje, będzie wieczne. Na przykład w 1990 r. Urząd pocztowy zdecydował, że Aberdeen robi się trochę zatłoczony. Dodali 0 na końcu AB1-5, co czyni go AB10-50, a następnie utworzyli między nimi kilka kodów pocztowych.

Za każdym razem, gdy tworzona jest nowa ulica, tworzony jest nowy kod pocztowy. Jest to część procesu uzyskiwania pozwolenia na budowę; lokalne władze są zobowiązane do aktualizowania tego na poczcie (nie że wszyscy to robią).

Ponadto, jak zauważyło wielu innych użytkowników, istnieją specjalne kody pocztowe, takie jak Girobank, GIR 0AA, i ten do listów do Świętego Mikołaja, SAN TA1 - prawdopodobnie nie chcesz nic tam publikować, ale wydaje się, że nie być objęty jakąkolwiek inną odpowiedzią.

Potem są kody pocztowe BFPO, które teraz zmieniają się na bardziej standardowy format . Oba formaty będą ważne. Na koniec jest Wikipedia Wikipedia z zagranicy .

+ ---------- + -------------------------------------- -------- +
| Kod pocztowy | Lokalizacja |
+ ---------- + -------------------------------------- -------- +
| AI-2640 | Anguilla |
| ASCN 1ZZ | Wyspa Wniebowstąpienia |
| STHL 1ZZ | Święta Helena |
| TDCU 1ZZ | Tristan da Cunha |
| BBND 1ZZ | Brytyjskie Terytorium Oceanu Indyjskiego |
| BIQQ 1ZZ | Brytyjskie Terytorium Antarktyczne |
| FIQQ 1ZZ | Falklandy |
| GX11 1AA | Gibraltar |
| PCRN 1ZZ | Wyspy Pitcairn |
| SIQQ 1ZZ | Georgia Południowa i Sandwich Południowy |
| TKCA 1ZZ | Wyspy Turks i Caicos |
+ ---------- + -------------------------------------- -------- +

Następnie należy wziąć pod uwagę, że Wielka Brytania „wyeksportowała” swój system kodów pocztowych do wielu miejsc na świecie. Wszystko, co potwierdzi kod pocztowy „UK”, również potwierdzi kody pocztowe wielu innych krajów.

Jeśli chcesz sprawdzić poprawność brytyjskiego kodu pocztowego, najbezpieczniejszym sposobem jest sprawdzenie aktualnego kodu pocztowego. Istnieje wiele opcji:

  • Ordnance Survey publikuje Code-Point Open na podstawie licencji na otwarte dane. Będzie trochę za późno, ale za darmo. Nie spowoduje to (prawdopodobnie - nie pamiętam) danych z Irlandii Północnej, ponieważ badanie Ordnance Survey nie ma tam żadnych uprawnień. Mapowanie w Irlandii Północnej jest przeprowadzane przez Ordnance Survey z Irlandii Północnej i mają one swój oddzielny, opłacony produkt Pointer . Możesz użyć tego i dołączyć kilka, które nie są dość łatwo objęte.

  • Royal Mail wydaje plik z kodem pocztowym (PAF) , w tym BFPO, co nie jestem pewien, że Code-Point Open to robi. Jest aktualizowany regularnie, ale kosztuje pieniądze (i czasami mogą być wredni). PAF zawiera pełny adres, a nie tylko kody pocztowe, oraz własny Przewodnik dla programistów . Grupa Użytkowników Otwartych Danych (ODUG) obecnie lobbuje za darmowym wydaniem PAF, oto opis ich pozycji .

  • Wreszcie istnieje Baza adresów . Jest to współpraca między Ordnance Survey, władzami lokalnymi, Royal Mail i firmą zajmującą się dopasowywaniem w celu stworzenia ostatecznego katalogu wszystkich informacji o wszystkich adresach w Wielkiej Brytanii (również były dość udane). Jest płatny, ale jeśli współpracujesz z władzami lokalnymi, departamentem rządowym lub służbą rządową, korzystanie z nich jest bezpłatne. Zawiera o wiele więcej informacji niż tylko kody pocztowe.

Ben
źródło
wyszukiwanie brzmi interesująco
SuperUberDuper
2
chociaż nie jest to odpowiedź, której szukał operacja, jest prawdopodobnie najbardziej użyteczna. To zachęci mnie do rozluźnienia zasad sprawdzania, które zamierzam zrobić.
John Hunt
22

Przyjrzałem się niektórym z powyższych odpowiedzi i odradzam stosowanie wzorca z odpowiedzi @ Dana (ok. 15 grudnia 2010 r.) , Ponieważ nieprawidłowo oznacza prawie 0,4% prawidłowych kodów pocztowych jako nieprawidłowe, podczas gdy inne nie .

Ordnance Survey zapewnia usługę o nazwie Code Point Open, która:

zawiera listę wszystkich obecnych jednostek kodu pocztowego w Wielkiej Brytanii

Uruchomiłem każdy z powyższych wyrażeń regularnych z pełną listą kodów pocztowych (6 lipca 13) z tych danych, używając 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"

Łącznie jest 1668 202 kodów pocztowych.

Poniżej podano liczby prawidłowych kodów pocztowych, które nie pasują do siebie $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

Oczywiście wyniki te dotyczą tylko prawidłowych kodów pocztowych, które zostały nieprawidłowo oznaczone jako nieprawidłowe. Więc:

'^.*$'
# => 0

Nie mówię nic o tym, który wzorzec jest najlepszy w zakresie odfiltrowywania nieprawidłowych kodów pocztowych.

RichardTowers
źródło
1
Czy to nie to, co mówię w mojej odpowiedzi i jeśli wybierasz się na dyskretną trasę, prawdopodobnie powinieneś zrobić je wszystkie i aktualizować, jeśli ktoś zmieni odpowiedź? Jeśli nie, przynajmniej podaj datę ostatniej edycji odpowiedzi, z której otrzymałeś odpowiedź, aby ludzie mogli zobaczyć, czy od tego czasu została zmieniona.
Ben
Uczciwy punkt. Odpowiednio zredagowane. Myślę, że to dodaje do dyskusji, że większość z tych wzorców nie wyklucza żadnego z kodów CPO, ale robi to najbardziej pozytywna (poprawna regex) odpowiedź. Przyszli czytelnicy: pamiętaj, że moje wyniki mogą być nieaktualne.
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)$

Wyrażenie regularne pasujące do prawidłowych kodów pocztowych w Wielkiej Brytanii. W brytyjskim systemie pocztowym nie wszystkie litery są używane na wszystkich pozycjach (tak samo jak w przypadku tablic rejestracyjnych pojazdów) i istnieją różne zasady, które to regulują. Ten wyrażenie regularne uwzględnia te reguły. Szczegóły dotyczące zasad: Pierwsza połowa kodu pocztowego Poprawne formaty [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] Wyjątki Pozycja - pierwsza. Przeciwwskazanie - QVX nieużywany Pozycja - druga. Przeciwwskazanie - IJZ nieużywany, z wyjątkiem pozycji GIR 0AA - trzecia. Ograniczenie - AEHMNPRTVXY używane tylko Pozycja - Naprzód. Przeciwwskazanie - ABEHMNPRVWXY Druga połowa kodu pocztowego Prawidłowe formaty [0–9] [AZ] [AZ] Wyjątki Pozycja - druga i trzecia. Przeciwwskazanie - CIKMOV nieużywany

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

Dan
źródło
1
Nie mam pojęcia, dlaczego ludzie głosowali za tą odpowiedzią - to poprawna regex
Ollie
Wyrażenie regularne nie działa dla kodów pocztowych „YO31” i „YO31 1” w Javscript.
Pratik Khadloya,
9
Nie sądzę, aby było to poprawne, ponieważ podany regex jest sprzeczny z opisem i sugeruje, że możesz mieć kody pocztowe zaczynające się od 0-9, czego nie możesz
Luigi Plinge
4
Wyrażenie regularne kończy się niepowodzeniem w przypadku około 6000 prawidłowych kodów pocztowych, więc odradzam. Zobacz moją odpowiedź .
RichardTowers
to nie działa na żadnym kodzie pocztowym pisanym małymi literami lub bez miejsca dla mnie
Dancer
14

Według tej tabeli w Wikipedii

wprowadź opis zdjęcia tutaj

Ten wzór obejmuje wszystkie przypadki

(?:[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})

Używając go na Androidzie \ Java użyj \\ d

AntPachon
źródło
Znalazłem tę najbardziej czytelną odpowiedź, chociaż szuka ona jedynie formy kodu pocztowego, a nie rzeczywistych poprawnych kodów zgodnie z rozwiązaniami, które pobierają informacje ze strony internetowej gov.uk, ale to wystarcza na mój przypadek użycia. Po tym, jak się z nim trochę pobawiłem (w pythonie), rozważyłem go do nieco bardziej zwartego, ale równoważnego wyrażenia regularnego, który pozwala również na opcjonalną spację: ([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

Większość odpowiedzi tutaj nie działała dla wszystkich kodów pocztowych, które mam w swojej bazie danych. W końcu znalazłem taki, który sprawdza się u wszystkich, korzystając z nowego wyrażenia regularnego dostarczonego przez rząd:

https://www.gov.uk/government/uploads/system/uploads/attachment_data/file/413338/Bulk_Data_Transfer_-_additional_validation_valid_from_March_2015.pdf

Nie ma go w żadnej z poprzednich odpowiedzi, więc zamieszczam go tutaj na wypadek, gdyby usunęli link:

^([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})$

AKTUALIZACJA: Zaktualizowano wyrażenie regularne, jak wskazał Jamie Bull. Nie jestem pewien, czy to był mój błąd podczas kopiowania, czy błąd w wyrażeniu regularnym rządu, link jest teraz wyłączony ...

AKTUALIZACJA: Jak znaleziono ctwheels, ten regex działa ze smakiem regex javascript. Zobacz jego komentarz do tego, który działa ze smakiem pcre (php).

Jesús Carrera
źródło
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})$powinno być ^([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})$- zauważ różnicę ;-)
Jamie Bull
1
Spot on! Zaktualizowałem moją odpowiedź. Dzięki!
Jesús Carrera
2
To jedyna odpowiedź tutaj, która działała w regexr.com i Notepad ++. Chociaż zmieniłem go na ([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})(usunąłem ^i $dodałem ?spację) dla regexr.com, aby znaleźć więcej niż jeden wynik i dla obu, aby znaleźć wynik, który nie ma separatora przestrzeni.
mythofechelon
@ctwheels to wyrażenie regularne dla smaku javascript. Jeśli Twój link nie powiedzie się, wybierz javascript, to zadziała. To świetny haczyk i zaktualizuję swoją odpowiedź.
Jesús Carrera
1
Wyrażenie regularne opublikowane w dokumentacji jest z natury niepoprawne. Całe wyrażenie należy owinąć w grupę, która nie jest w stanie przechwycić, (?:)a następnie umieścić wokół niego kotwice. Zobacz, jak zawodzi tutaj . Aby uzyskać więcej informacji, zobacz moją odpowiedź tutaj . ^(?:([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}))$jest poprawionym wyrażeniem regularnym.
ctwheels
12

Stary post, ale wciąż dość wysoki w wynikach Google, więc pomyślałem, że zaktualizuję. Ten dokument z 14 października definiuje wyrażenie regularne kodu pocztowego w Wielkiej Brytanii jako:

^([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})$

z:

https://www.gov.uk/government/uploads/system/uploads/attachment_data/file/359448/4__Bulk_Data_Transfer_-_additional_validation_valid.pdf

Dokument wyjaśnia również logikę tego procesu. Ma jednak błąd (pogrubiony), a także pozwala na pisanie małymi literami, co, choć nie jest normalne, jest zmienioną wersją:

^(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})$

Działa to z nowymi londyńskimi kodami pocztowymi (np. W1D 5LH), których nie miały poprzednie wersje.

martwy krab
źródło
Wygląda na to, że błąd wyróżniony pogrubioną czcionką został naprawiony w dokumencie, ale nadal wolę twoje wyrażenie regularne, ponieważ jest łatwiejsze do odczytania.
Profesor programowania
5
Chciałbym tylko powiedzieć, że spacja jest opcjonalna, zmieniając spację na \ s? ponieważ przestrzeń nie jest wymagana dla czytelności.
Profesor programowania
Wyrażenie regularne opublikowane w dokumentacji jest z natury niepoprawne. Całe wyrażenie należy owinąć w grupę, która nie jest w stanie przechwycić, (?:)a następnie umieścić wokół niego kotwice. Zobacz, jak zawodzi tutaj . Aby uzyskać więcej informacji, zobacz moją odpowiedź tutaj . ^(?:([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}))$jest poprawionym wyrażeniem regularnym.
ctwheels
10

Oto regex, który Google obsługuje w swojej domenie i18napis.appspot.com :

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}
Alix Axel
źródło
10

Kody pocztowe mogą ulec zmianie, a jedynym prawdziwym sposobem sprawdzania poprawności kodu pocztowego jest posiadanie pełnej listy kodów pocztowych i sprawdzenie, czy istnieje.

Ale wyrażenia regularne są przydatne, ponieważ:

  • są łatwe w użyciu i wdrażaniu
  • są krótkie
  • są szybkie w uruchomieniu
  • są dość łatwe w utrzymaniu (w porównaniu do pełnej listy kodów pocztowych)
  • nadal wychwytuje większość błędów wejściowych

Ale wyrażenia regularne są trudne do utrzymania, szczególnie dla kogoś, kto nie wymyślił tego w pierwszej kolejności. Więc musi to być:

  • tak łatwe do zrozumienia, jak to możliwe
  • względnie przyszłościowy dowód

Oznacza to, że większość wyrażeń regularnych w tej odpowiedzi nie jest wystarczająco dobra. Np. Widzę to[A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRV-Y] będzie pasować do obszaru kodu pocztowego w postaci AA1A - ale będzie to ból w szyi, jeśli i kiedy zostanie dodany nowy obszar kodu pocztowego, ponieważ trudno jest zrozumieć, które obszary kodu pocztowego pasują.

Chcę również, aby moje wyrażenie regularne dopasowywało pierwszą i drugą połowę kodu pocztowego jako dopasowania w nawiasach.

Więc wpadłem na to:

(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})

W formacie PCRE można go zapisać w następujący sposób:

/^
  ( 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

Dla mnie jest to odpowiednia równowaga między walidacją w jak największym stopniu, przy jednoczesnym zabezpieczeniu na przyszłość i umożliwieniu łatwej konserwacji.

Andre
źródło
Nie jestem pewien, dlaczego zostałeś odrzucony - działa to ze wszystkimi poprawnymi kodami pocztowymi, które na niego rzuciłem, oraz spacjami, których wiele powyższych odpowiedzi nie obsługuje poprawnie. Czy ktoś zechciałby wyjaśnić, dlaczego?
Jon
1
@Jon Pasuje także wtedy, gdy inne postacie są dodawane na początku lub na końcu, np. aSW1A 1AAasfgDopasowane do mnie (nie głosowałem jednak, ponieważ wydaje się, że można to łatwo naprawić)
dekoduje
9

Szukałem regexu kodu pocztowego w Wielkiej Brytanii przez ostatni dzień i natknąłem się na ten wątek. Przeszedłem przez większość powyższych sugestii i żadna z nich nie działała dla mnie, więc wymyśliłem swój regex, który, o ile wiem, przechowuje wszystkie ważne kody pocztowe w Wielkiej Brytanii od stycznia 2013 r. (Według najnowszej literatury z Royal Mail).

Wyrażenie regularne i niektóre proste sprawdzanie kodu PHP znajduje się poniżej. UWAGA: - Pozwala na pisanie małymi lub dużymi kodami pocztowymi oraz anomalię GIR 0AA, ale aby poradzić sobie z bardziej niż prawdopodobną obecnością spacji w środku wprowadzonego kodu pocztowego, wykorzystuje również prosty str_replace do usunięcia spacji przed testowaniem przeciw wyrażeniu regularnemu. Wszelkie rozbieżności poza tym i sama Royal Mail nawet nie wspominają o nich w swojej literaturze (patrz http://www.royalmail.com/sites/default/files/docs/pdf/programmers_guide_edition_7_v5.pdf i zacznij czytać od strony 17) !

Uwaga: we własnej literaturze Royal Mail (link powyżej) istnieje niewielka dwuznaczność wokół 3. i 4. pozycji oraz wyjątków, jeśli te znaki są literami. Skontaktowałem się bezpośrednio z Royal Mail, aby to wyjaśnić i ich własnymi słowami: „List na czwartej pozycji kodu zewnętrznego w formacie AANA NAA nie ma wyjątków, a wyjątki na trzeciej pozycji dotyczą tylko ostatniej litery kodu zewnętrznego z format ANA NAA. ” Prosto z pyska konia!

<?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>";

    }

?>

Mam nadzieję, że pomoże to każdemu, kto spotyka ten wątek, szukając rozwiązania.

Dan Solo
źródło
1
Byłbym ciekawy, który przykładowy kod pocztowy zawiódł opublikowany?
Zhaph - Ben Duguid
Nie mogę podać konkretnego kodu pocztowego (bez dostępu do pełnej listy PAF), ale kody pocztowe w formacie ANA NAA potencjalnie zawiodą, ponieważ litery P i Q są dozwolone na 3. pozycji, a kody pocztowe w formacie AANA NAA potencjalnie również zawodzi, ponieważ czwarta pozycja pozwala na wszystkie litery (regex podany w powyższej zaakceptowanej odpowiedzi nie uwzględnia żadnej z nich). Jak mówię, korzystam tylko z bieżącej porady Royal Mail - w momencie udzielenia powyższej odpowiedzi być może regex był w pełni zgodny.
Dan Solo
Dzięki za heads-up - widzę, że „P” wydaje się być dodane jako trzecie na akceptowalnej pozycji (z twojego połączonego dokumentu), ale nie Q - ale gdzie czytasz, że „czwarta pozycja dopuszcza wszystkie litery”? Doktor nie wspomina o „czwartej pozycji”, o ile widzę, więc przeczytałem to jako „trzecią literę, niezależnie od rzeczywistej pozycji”.
Zhaph - Ben Duguid
1
Właśnie otrzymałem wiadomość od zespołu wsparcia Royal Mail i moja interpretacja zasad jest poprawna. Litera na czwartej pozycji Kodu Zewnętrznego (np. AANA NAA) nie ma wyjątków, a wyjątki na trzeciej pozycji dotyczą tylko ostatniej litery (np. ANA NAA). Prosto z pyska konia.
Dan Solo
1
@DanSolo To wyrażenie regularne zwróci prawdziwe dopasowanie dla pierwszej połowy poprawnego kodu pocztowego bez wewnętrznego kodu, np. SW1ALub BD25bez drugiej połowy (lub przynajmniej tak zrobiłem dla mnie)
dekoduje
7

Oto regex oparty na formacie określonym w dokumentach powiązanych z odpowiedzią marcj:

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

Jedyną różnicą między tym a specyfikacją jest to, że 2 ostatnie znaki nie mogą być w [CIKMOV] zgodnie ze specyfikacją.

Edycja: Oto kolejna wersja, która sprawdza ograniczenia znaków końcowych.

/^[A-Z]{1,2}[0-9][0-9A-Z]? ?[0-9][A-BD-HJLNP-UW-Z]{2}$/
Will Tomlins
źródło
Kod pocztowy w Wielkiej Brytanii jest znacznie bardziej skomplikowany niż tylko akceptacja A-Z- Qnigdy nie jest dozwolony, Vjest używany tylko oszczędnie itp., W zależności od położenia znaku.
Zhaph - Ben Duguid
2
To może nie mieć znaczenia, jeśli chcesz sprawdzić składnię. Jak zauważyło wiele innych osób, tylko wyszukiwanie w aktualnej bazie danych jest prawie poprawne, a nawet wtedy pojawia się problem z aktualnością bazy danych. Dla mnie ta reguła sprawdzania składni jest więc jasna, prosta i użyteczna.
Rick-777,
5

Niektóre z powyższych wyrażeń regularnych są nieco restrykcyjne. Zwróć uwagę, że prawdziwy kod pocztowy: „W1K 7AA” nie powiedzie się, biorąc pod uwagę regułę „Pozycja 3 - AEHMNPRTVXY użyto tylko” powyżej, ponieważ „K” zostanie niedozwolone.

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})$

Wydaje się nieco dokładniejszy, zobacz artykuł w Wikipedii zatytułowany „Kody pocztowe w Wielkiej Brytanii” .

Zauważ, że regex wymaga tylko wielkich liter.

Większe pytanie dotyczy tego, czy ograniczasz wprowadzanie danych przez użytkownika, aby zezwalać tylko na istniejące kody pocztowe, czy też próbujesz po prostu powstrzymać użytkowników przed wprowadzaniem kompletnych śmieci do pól formularza. Prawidłowe dopasowanie każdego możliwego kodu pocztowego i sprawdzenie go w przyszłości jest trudniejszą łamigłówką i prawdopodobnie nie jest tego warte, chyba że jesteś HMRC.

Minglis
źródło
Wygląda na to, że poczta się zmieniła, ale rząd jest nieco opóźniony :(
Zhaph - Ben Duguid
4
Używam tego: "^ ([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}) $ "Podoba mi się, ponieważ pozwala na pisanie dużymi i małymi literami i sprawia, że ​​przestrzeń jest opcjonalna - lepsza pod względem użyteczności, jeśli nie w 100% poprawna!
bigtv
4

oto jak radziliśmy sobie z problemem brytyjskiego kodu pocztowego:

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

Wyjaśnienie:

  • spodziewaj się 1 lub 2 znaków az, górna lub dolna grzywna
  • spodziewaj się 1 lub 2 liczb
  • spodziewaj się 0 lub 1 az char, górna lub dolna grzywna
  • opcjonalne miejsce dozwolone
  • oczekuj 1 cyfry
  • spodziewaj się 2 az, grzywny górnej lub dolnej

Otrzymuje większość formatów, następnie używamy db, aby sprawdzić, czy kod pocztowy jest rzeczywiście prawdziwy, dane te są sterowane przez openpoint https://www.ordnancesurvey.co.uk/opendatadownload/products.html

mam nadzieję że to pomoże

Alex Stephens
źródło
Pozwala AANNA NAAto na nieprawidłowy format .
ctwheels,
Dlatego odpowiedź brzmi „To dostaje większość formatów”. :)
Alex Stephens
4

Podstawowe zasady:

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

Kody pocztowe w Wielkiej Brytanii (lub kody pocztowe, jak się je nazywa) składają się z pięciu do siedmiu znaków alfanumerycznych oddzielonych spacją. Zasady określające, które postacie mogą pojawiać się na poszczególnych pozycjach, są dość skomplikowane i pełne wyjątków. Dlatego właśnie pokazane wyrażenie regularne przestrzega podstawowych zasad.

Kompletne zasady:

Jeśli potrzebujesz wyrażenia regularnego, które zaznacza wszystkie pola reguł kodu pocztowego kosztem czytelności, proszę:

^(?:(?:[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)$

Źródło: https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9781449327453/ch04s16.html

Testowane na bazie danych naszych klientów i wydaje się być całkowicie dokładne.

Raphos
źródło
4

Korzystam z następującego wyrażenia regularnego, które przetestowałem na wszystkich prawidłowych kodach pocztowych w Wielkiej Brytanii. Opiera się na zalecanych regułach, ale jest maksymalnie skondensowany i nie korzysta ze specjalnych reguł wyrażeń regularnych specyficznych dla języka.

([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})

Zakłada się, że kod pocztowy został przekonwertowany na wielkie litery i nie ma znaków wiodących ani końcowych, ale zaakceptuje opcjonalną spację między kodem zewnętrznym a kodem incode.

Specjalny kod pocztowy „GIR0 0AA” jest wykluczony i nie będzie sprawdzany, ponieważ nie znajduje się na oficjalnej liście kodów pocztowych i, o ile wiem, nie będzie używany jako zarejestrowany adres. Dodanie go powinno być trywialne jako specjalny przypadek, jeśli jest to wymagane.

Dłuto
źródło
4

Chciałem prostego wyrażenia regularnego, w którym można pozwolić na zbyt wiele, ale nie odmawiać prawidłowego kodu pocztowego. Poszedłem z tym (wejście jest ciągiem okrojonym / przyciętym):

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

Umożliwia to stosowanie możliwie najkrótszych kodów pocztowych, takich jak „L1 8JQ”, a także najdłuższych, takich jak „OL14 5ET”.

Ponieważ pozwala na maksymalnie 8 znaków, pozwoli również na niepoprawne 8-znakowe kody pocztowe, jeśli nie będzie spacji: „OL145ETX”. Ale znowu, jest to proste wyrażenie, gdy jest to wystarczająco dobre.

Henrik N.
źródło
Przepraszam. Myślę, że przegapiłem / i, kiedy testowałem wczoraj.
John
3

Pierwsza połowa prawidłowego formatu kodu pocztowego

  • [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]

Wyjątki
Pozycja 1 - QVX nieużywany
Pozycja 2 - IJZ nieużywany z wyjątkiem GIR 0AA
Pozycja 3 - AEHMNPRTVXY tylko używany
Pozycja 4 - ABEHMNPRVWXY

Druga połowa kodu pocztowego

  • [0–9] [AZ] [AZ]

Wyjątki
Pozycja 2 + 3 - CIKMOV nieużywany

Pamiętaj, że nie są używane wszystkie możliwe kody, więc ta lista jest koniecznym, ale niewystarczającym warunkiem prawidłowego kodu. Może łatwiej jest po prostu dopasować listę wszystkich ważnych kodów?

Martin Beckett
źródło
3

Aby sprawdzić, czy kod pocztowy ma prawidłowy format, zgodnie z podręcznikiem programisty 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})$

Wszystkie kody pocztowe na doogal.co.uk są zgodne, z wyjątkiem tych, które nie są już używane.

Dodanie ?spacji i użycie dopasowania bez rozróżniania wielkości liter, aby odpowiedzieć na to pytanie:

'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" ]
Jackson Pauls
źródło
3

Ta zezwala na puste spacje i tabulatory z obu stron na wypadek, gdyby nie chcesz nie sprawdzać poprawności, a następnie przyciąć ją oddzielić.

^\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*$)
Matas Vaitkevicius
źródło
To jedyny wzór, który działał dla mnie przy użyciu c # (System.Text.RegularExpressions) z przykładami opisanymi w pierwotnym pytaniu
MattjeS
Jest to zepsuty regex rządu brytyjskiego, który nie sprawdza poprawności niektórych prawidłowych formatów.
ctwheels,
@ctwheels Cześć, czy możesz podać nieprawidłowy kod pocztowy, dziękuję.
Matas Vaitkevicius
Np. AAA 1AANie jest prawidłowym formatem: zobacz moją odpowiedź, aby uzyskać wyjaśnienie i poprawkę.
ctwheels,
2

Aby dodać do tej listy bardziej praktyczne wyrażenie, którego używam, które pozwala użytkownikowi wprowadzić empty string:

^$|^(([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}))$

Ten regex pozwala na pisanie wielkimi i małymi literami z opcjonalną spacją pomiędzy nimi

Z punktu widzenia twórców oprogramowania ta regex jest przydatna w przypadku oprogramowania, w którym adres może być opcjonalny. Na przykład, jeśli użytkownik nie chce podać swoich danych adresowych

użytkownik1
źródło
1

Spójrz na kod python na tej stronie:

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

Muszę parsować kod pocztowy. Wymaganie jest dość proste; Muszę parsować kod pocztowy na outcode i (opcjonalnie) incode. Dobrą wiadomością jest to, że nie muszę przeprowadzać żadnej weryfikacji - muszę jedynie rozdrobnić to, co otrzymałem w sposób dość inteligentny. Nie mogę dużo założyć na temat importu pod względem formatowania, tj. Wielkości liter i spacji. Ale to nie są złe wieści; zła wiadomość jest taka, że ​​muszę to wszystko robić w RPG. :-(

Niemniej jednak rzuciłem małą funkcję Pythona, aby wyjaśnić moje myślenie.

Użyłem go do przetwarzania kodów pocztowych.

Rudiger Wolf
źródło
1

Otrzymaliśmy specyfikację:

Kody pocztowe w Wielkiej Brytanii muszą mieć jedną z następujących postaci (z jednym wyjątkiem, patrz poniżej): 
    § A9 9AA 
    § A99 9AA
    § AA9 9AA
    § AA99 9AA
    § A9A 9AA
    § AA9A 9AA
gdzie A oznacza znak alfabetyczny, a 9 oznacza znak numeryczny.
W przypadku znaków alfabetycznych obowiązują dodatkowe zasady:
    § Znak na pozycji 1 nie może być Q, V ani X
    § Znak na pozycji 2 nie może być I, J ani Z
    § Znak na pozycji 3 nie może być I, L, M, N, O, P, Q, R, V, X, Y lub Z
    § Znak na pozycji 4 nie może być C, D, F, G, I, J, K, L, O, Q, S, T, U ani Z
    § Znaki na skrajnie prawej pozycji nie mogą być C, I, K, M, O ani V.
Jedynym wyjątkiem, który nie jest zgodny z tymi ogólnymi zasadami, jest kod pocztowy „GIR 0AA”, który jest specjalnym ważnym kodem pocztowym.

Wymyśliliśmy to:

/^([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

Ale uwaga - pozwala to na dowolną liczbę spacji między grupami.

paulslater19
źródło
2
paulslater19, niestety twoje rozwiązanie pozwala na stosowanie kodów pocztowych A99A 9AA.
1

Mam regex do sprawdzania poprawności kodów pocztowych w Wielkiej Brytanii.

Działa to dla wszystkich typów kodów pocztowych wewnętrznych lub zewnętrznych

^((([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}))$

Działa to dla wszystkich typów formatów.

Przykład:

AB10 --------------------> TYLKO KOD POCZTOWY ZEWNĘTRZNY

A1 1AA ------------------> POŁĄCZENIE KODU POCZTOWEGO (ZEWNĘTRZNY I WEWNĘTRZNY)

WC2A --------------------> ZEWNĘTRZNY

Szybki Mistrz
źródło
1

Przyjęta odpowiedź odzwierciedla zasady podane przez Royal Mail, chociaż w wyrażeniu regularnym występuje literówka. Wydaje się, że ta literówka była tam również na stronie gov.uk (tak jak na stronie archiwum XML).

W formacie A9A 9AA reguły zezwalają znakowi P na trzeciej pozycji, a wyrażenie regularne tego nie zezwala. Poprawnym wyrażeniem regularnym byłoby:

(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}) 

Skrócenie tego powoduje wyrażenie regularne (które używa składni 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})

Zawiera także opcjonalną spację między pierwszym a drugim blokiem.

Stieb
źródło
1

To, co znalazłem w prawie wszystkich odmianach i wyrażeniu regularnym z pliku PDF przesyłania zbiorczego, i to, co znajduje się na stronie wikipedia, jest takie, szczególnie dla wyrażenia regularnego wikipedia, po pierwszym | (pionowym pasku) musi być ^. Zrozumiałem to, testując dla AA9A 9AA, ponieważ w przeciwnym razie sprawdzenie formatu dla A9A 9AA to potwierdzi. Na przykład sprawdzenie EC1D 1BB, które powinno być nieprawidłowe, powraca jako ważne, ponieważ C1D 1BB jest prawidłowym formatem.

Oto, co wymyśliłem dla dobrego wyrażenia regularnego:

^([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})$
Andrew Schliewe
źródło
1

Dzięki testom empirycznym i obserwacji, a także potwierdzeniu za pomocą https://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom#Validation , oto moja wersja wyrażenia regularnego Python, który poprawnie analizuje i weryfikuje brytyjski kod pocztowy:

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})'

Ten wyrażenie regularne jest proste i zawiera grupy przechwytywania. Nie obejmuje ona wszystkich sprawdzeń poprawności legalnych kodów pocztowych w Wielkiej Brytanii, ale uwzględnia jedynie pozycje literowe vs. liczbowe.

Oto jak użyłbym tego w kodzie:

@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

Oto testy jednostkowe:

@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)
jontsai
źródło
0

Potrzebowałem wersji, która działałaby w SAS z PRXMATCHpowiązanymi funkcjami, więc wymyśliłem:

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

Przypadki testowe i uwagi:

/* 
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;
user667489
źródło
0

Poniższa metoda sprawdzi kod pocztowy i dostarczy pełne informacje

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!"}
Aathi
źródło