RegEx для відповідності поштових індексів Великобританії


186

Я після регексу, який підтверджує повний комплексний поштовий індекс у Великобританії лише у рядку введення. Усі незвичайні форми поштових індексів повинні бути охоплені так само, як і звичайні. Наприклад:

Сірники

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

Немає відповідності

  • aWC2H 7LT
  • WC2H 7LTa
  • WC2H

Як вирішити цю проблему?


2
@axrwkr, що не здається корисним
Kieran Benton

8
Валідація поштових індексів у Великобританії - JavaScript та PHP Я не зміг отримати прийняту відповідь на відповідність дійсним поштовим індексам, але я знайшов це, і він відповідає дійсним поштовим індексам. Для клієнтської перевірки версію JavaScript можна використовувати так само, як і для перевірки на сервері, переписування JavaScript як C # досить просто. Він навіть переформатує поштовий індекс, щоб він мав пробіл, тому якщо ви введете поштовий індекс як W1A1AA, на додаток до перевірки, він переформатує його на W1A 1AA. Він навіть має справу з незвичайними поштовими індексами на різних британських територіях.

2
Надане посилання не працює для форматів "AA1A 1AA". Довідка: dhl.com.tw/content/dam/downloads/tw/express/forms/…
Ентоні Скайф

1
Якщо ви просто хочете підтвердити поштовий індекс, ми пропонуємо безкоштовну (необхідну реєстрацію) валідацію кінцевої точки API REST - developers.alliescomputing.com/postcoder-web-api/address-lookup/…
Stephen Keable

1
Гарне питання. Я думаю, що варто було б включити до свого списку нечасті приклади центральних манчестерських поштових індексів, таких як "M1 3HZ". Багато людей не знають комбо з 1 літерою 1.
Мартін Столяр

Відповіді:


208

Я рекомендую ознайомитись зі стандартами даних уряду Великобританії щодо поштових індексів [посилання тепер мертве; архів XML , див. Вікіпедію для обговорення]. Існує короткий опис даних, а додана схема xml забезпечує регулярне вираження. Це може бути не саме те, що ви хочете, але було б гарною відправною точкою. RegEx незначно відрізняється від XML, оскільки символом P на третьому положенні у форматі A9A 9AA дозволено задане визначення.

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

Як зазначалося в обговоренні Вікіпедії, це дозволить отримати деякі не реальні поштові індекси (наприклад, ті, що починають AA, ZY), і вони нададуть більш суворий тест, який ви можете спробувати.


52
І це reg ex із необов'язковим пробілом між двома сегментами (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
Можливо, буде гарною ідеєю підвести справжній вираз до відповіді, оскільки сторінки, здається, закінчуються щороку ...
pauloya

7
Зауважте, що цей регулярний вираз призначений для XML-схеми, яка, очевидно, дещо відрізняється від інших ароматів регулярного
генезу

6
Я не можу змусити це працювати в JavaScript. Це працює лише з певними двигунами-регексами?
NickG

12
Насправді вони змінили це: Масова передача даних :^([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

Схоже, ми будемо використовувати ^(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})$, що є дещо зміненою версією, яку переглянув Мінгліс вище.

Однак нам доведеться дослідити, що саме є правилами, оскільки, як видається, в різних перелічених рішеннях застосовуються різні правила щодо того, які літери дозволені.

Після деяких досліджень ми знайшли ще трохи інформації. Мабуть, на сторінці "govtalk.gov.uk" вказується на специфікацію поштового індексу govtalk-поштові індекси . Це вказує на XML-схему на XML-схемі, яка надає «псевдо-регулярний вираз» правил поштового коду.

Ми зробили це і трохи попрацювали над цим, щоб дати нам такий вираз:

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

Це робить пробіли необов’язковими, але обмежує вас одним простором (замініть значення "&" на "{0,} для необмежених пробілів)". Це передбачає, що весь текст повинен бути великим.

Якщо ви хочете дозволити малі регістри з будь-якою кількістю пробілів, використовуйте:

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

Це не охоплює закордонні території і лише застосовує формат, НЕ існування різних областей. Він заснований на таких правилах:

Можна приймати такі формати:

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

Де:

  • 9 може бути будь-яке одноцифрове число.
  • А може бути будь-яка літера, крім Q, V або X.
  • B може бути будь-якою буквою, крім I, J або Z.
  • C може бути будь-якою буквою, крім I, L, M, N, O, P, Q, R, V, X, Y або Z.
  • D може бути будь-якою буквою, крім I, J або Z.
  • Е може бути будь-яким з A, B, E, H, M, N, P, R, V, W, X або Y.
  • Z може бути будь-якою буквою, крім C, I, K, M, O або V.

Найкращі побажання

Колін


2
Чудова відповідь, я додав у заморські^(([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}))$
Девід Бредшоу

Навіщо вказувати {0,}замість *необмежених необов’язкових пробілів?
Code Animal

76

Я недавно опублікував відповідь на це питання на британських поштових індексів для мови R . Я виявив, що схема регулярного виразів уряду Великобританії невірна і не може належним чином перевірити деякі поштові індекси. На жаль, багато відповідей тут базуються на цій неправильній схемі.

Я викладу деякі з цих питань нижче і надам переглянуте регулярне вираження, яке насправді працює.


Примітка

Моя відповідь (і регулярні вирази взагалі):

  • Лише підтверджує формати поштових індексів .
  • Не забезпечує законного існування поштового індексу .
    • Для цього використовуйте відповідний API! Дивіться відповідь Бена для отримання додаткової інформації.

Якщо вас не хвилює поганий вираз і просто хочете перейти до відповіді, прокрутіть униз до розділу Відповіді .

Поганий реджекс

Регулярні вирази в цьому розділі не повинні використовуватися.

Це невдалий підсумок, який надав розробникам уряд Великобританії (не впевнений, наскільки довго буде працювати це посилання, але ви можете бачити це в їхній документації щодо масового перенесення даних ):

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

Проблеми

Проблема 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})$

Перше, що зроблять більшість розробників - це просто стерти новий рядок, не думаючи двічі. Тепер регулярний вираз не збігається з поштовими кодами з пробілами в них (крім GIR 0AAпоштового індексу).

Щоб вирішити цю проблему, символ нового рядка слід замінити символом пробілу:

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

Завдання 2 - Межі

Дивіться регекс тут .

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

Регекс поштового коду неправильно закріплює регулярний вираз. Кожен, хто використовує цей регулярний вираз для перевірки поштових індексів, може бути здивований, якщо таке значення начебто fooA11 1AAпроходить. Це тому, що вони прив’язали початок першого варіанту та кінець другого варіанту (незалежно один від одного), як зазначено в регулярній виразці.

Це означає, що ^(стверджує позицію на початку рядка) працює лише над першим варіантом ([Gg][Ii][Rr] 0[Aa]{2}), тому другий варіант підтвердить будь-які рядки, що закінчуються в поштовому індексі (незалежно від того, що відбувається раніше).

Так само перший варіант не прив’язаний до кінця рядка $, тому GIR 0AAfooвін також прийнятий.

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

Щоб виправити цю проблему, обидва варіанти повинні бути загорнуті в іншу групу (або групу, яка не захоплює), і якір, розміщений навколо цього:

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

Проблема 3 - Неправильний набір символів

Дивіться регекс тут .

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

Тут відсутній регулярний вираз, -щоб вказати діапазон символів. Наразі, якщо поштовий індекс є у форматі ANA NAA(де Aпозначає букву і Nпозначає число), і він починається з чого-небудь іншого, крім Aабо Z, він вийде з ладу.

Це означає, що вона буде відповідати A1A 1AAі Z1A 1AA, але ні B1A 1AA.

Щоб виправити цю проблему, символ -слід розмістити між відповідним набором символів Aта Zу ньому:

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

Проблема 4 - Неправильний набір символів

Дивіться регекс тут .

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

Я клянусь, вони навіть не тестували цю річ, перш ніж публікувати її в Інтернеті. Вони зробили неправильний набір символів необов’язковим. Вони зробили [0-9]варіант у четвертому під-варіанті варіанту 2 (група 9). Це дозволяє регулярному вираженню збігатися з неправильно відформатованими поштовими кодами типу AAA 1AA.

Щоб виправити цю проблему, замість цього зробіть наступний клас символів необов’язковим (а згодом встановіть [0-9]відповідність точно один раз):

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

Завдання 5 - Продуктивність

Продуктивність цього регексу надзвичайно низька. По-перше, вони розмістили найменш ймовірний варіант візерунка, який повинен відповідати GIR 0AAна початку. Скільки користувачів, ймовірно, мають цей поштовий індекс порівняно з будь-яким іншим поштовим індексом; певно, ніколи? Це означає, що кожного разу, коли використовується регулярний вираз, він повинен спочатку вичерпати цей варіант, перш ніж перейти до наступного варіанту. Щоб побачити, як впливає на продуктивність, перевірте кількість кроків, зроблених оригінальним регулярним виразом (35) проти того ж регексу після перевернення параметрів (22).

Друга проблема з продуктивністю пояснюється тим, як структурований весь регулярний вираз. Немає сенсу зворотного відстеження за кожним варіантом, якщо не вдалося. Спосіб структурування поточного регулярного вираження може бути значно спрощений. Я надаю виправлення цього в розділі Відповідь .

Завдання 6 - Проміжки

Дивіться регекс тут

Це само по собі не може вважатися проблемою , але це викликає занепокоєння у більшості розробників. Пробіли в регулярному виразі не є обов'язковими, а це означає, що користувачі, які вводять свої поштові індекси, повинні розміщувати пробіл у поштовому індексі. Це легко виправити шляхом простого додавання ?після пробілів, щоб зробити їх необов’язковими. Дивіться відповідь розділ для виправлення.


Відповідь

1. Закріплення Регексу уряду Великобританії

Виправлення всіх питань, викладених у розділі Проблеми та спрощення шаблону, дає наступний, коротший, більш стислий зразок. Ми також можемо видалити більшість груп, оскільки ми перевіряємо поштовий індекс у цілому (а не окремі частини):

Дивіться регекс тут

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

Далі це можна скоротити, видаливши всі діапазони з одного з випадків (верхнього або нижнього регістру) та використовуючи прапор, нечутливий до регістру. Примітка : Деякі мови не мають такої мови, тому використовуйте довшу вище. Кожна мова по-різному реалізує прапор нечутливості регістру.

Дивіться регекс тут .

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

Коротше знову замінимо [0-9]на \d(якщо ваш регекс-движок підтримує це):

Дивіться регекс тут .

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

2. Спрощені візерунки

Без забезпечення конкретних буквених символів можна використовувати наступне (майте на увазі спрощення з 1. Виправлення Regex уряду Великобританії також було застосовано тут):

Дивіться регекс тут .

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

І навіть далі, якщо вас не хвилює особливий випадок GIR 0AA:

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

3. Складні візерунки

Я не пропоную надмірно підтвердити поштовий індекс, оскільки нові райони, райони та підрайони можуть з’являтися в будь-який момент часу. Те, що я пропоную потенційно , - це додаткова підтримка кращих справ. Деякі особливі випадки існують і окреслені в цій статті у Вікіпедії .

Ось складні регекси, які включають підрозділи 3. (3.1, 3.2, 3.3).

Що стосується закономірностей у 1. Закріплення Регексу уряду Великобританії :

Дивіться регекс тут

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

А стосовно 2. Спрощені патерни :

Дивіться регекс тут

^(([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 Британські заморські території

Зараз у статті Вікіпедії зазначено (деякі формати трохи спрощені):

  • AI-1111: Ангіла
  • ASCN 1ZZ: Острів Вознесіння
  • STHL 1ZZ: Свята Єлена
  • TDCU 1ZZ: Трістан да Кунья
  • BBND 1ZZ: Британська територія Індійського океану
  • BIQQ 1ZZ: Британська територія Антарктики
  • FIQQ 1ZZ: Фолклендські острови
  • GX11 1ZZ: Гібралтар
  • PCRN 1ZZ: Острови Піткерн
  • SIQQ 1ZZ: Південна Джорджія та Південні Сандвічеві острови
  • TKCA 1ZZ: Острови Теркс і Кайкос
  • BFPO 11: Акротірі та Декелія
  • ZZ 11& GE CX: Бермудські острови (згідно з цим документом )
  • KY1-1111: Кайманові острови (згідно з цим документом )
  • VG1111: Британські Віргінські острови (згідно з цим документом )
  • MSR 1111: Монтсеррат (згідно з цим документом )

Всеохоплюючий регулярний вираз, який відповідає лише британським заморським територіям, може виглядати так:

Дивіться регекс тут .

^((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 Поштове відділення Британських сил

Незважаючи на те, що вони нещодавно змінили його для кращого узгодження з британською системою поштових індексів BF#(де #представляється число), вони вважаються необов'язковими альтернативними поштовими індексами . Ці поштові індекси дотримуються (редагують) формат, з BFPOнаступними 1-4 цифрами:

Дивіться регекс тут

^BFPO ?\d{1,4}$

3.3 Санта?

Є ще один особливий випадок із Дідом (як згадується в інших відповідях): SAN TA1це дійсний поштовий індекс. Зворотний вираз для цього дуже просто:

^SAN ?TA1$

4
Спрощені візерунки - це дійсно хороший варіант використання. Я вважаю, що найкраще не бути занадто обмежувальним з регулярним виразом, тому що вам потрібно переконатися, що він оновлюється будь-якими змінами, або у вас можуть бути дуже розлючені користувачі. Я вважаю, що краще злегка збігатися зі спрощеним регулярним виразом, щоб усунути очевидні помилки, а потім застосувати подальші перевірки, такі як пошук адреси (або електронний лист підтвердження у випадку регексу електронної пошти), щоб підтвердити дійсність.
Джеймс Койл

2
Відмінний і ретельний аналіз.
Стів

1
Блискуча відповідь на стільки рівнів. Зрештою, я пішов з вашим другим спрощеним шаблоном. Оскільки у мене фактично є БД із усіма поштовими індексами у Великобританії, мені просто потрібен перший прохід, щоб побачити, чи потенційно містить адресний рядок дійсний поштовий індекс, тому я не переймаюся помилковими позитивами (оскільки фактичний пошук викорінить їх) , але я дбаю про помилкові негативи. І швидкість теж має значення.
Джон Пауелл

Існує так багато проблем із системою поштових індексів у Великобританії, явно створених комітетом до епохи комп'ютера, але питання змінної довжини та пробілів є одним із найбільш згубних. Я бачив всілякі жахи, включаючи прокладки поштових індексів на зразок E1 5JX до E1 5JX, тобто з трьома пробілами, щоб він добре узгоджувався з SW18 5HA в Excel (вставляйте прикро невідповідне програмне забезпечення вибору для управління адресами). Єдине розумне рішення - ІМХО - викреслити всі пробіли, щоб поштовий індекс був єдиним рядком, перш ніж він з’явиться десь поблизу Еластик, Солр, Постгрес тощо.
Джон Пауелл,

45

Не існує такого поняття, як вичерпний регулярний вираз поштового індексу Великобританії, який би міг підтвердити поштовий індекс. Ви можете перевірити, чи є поштовий індекс у правильному форматі, використовуючи регулярний вираз; не те, що насправді існує.

Поштові індекси довільно складні і постійно змінюються. Наприклад, вихідний код W1не може, і ніколи, не має кожного номера між 1 і 99 для кожної області поштового індексу.

Ви не можете очікувати, що зараз існує, щоб бути правдою вічно. Наприклад, у 1990 році поштове відділення вирішило, що Абердін стає дещо переповненим. Вони додали 0 до кінця AB1-5, зробивши його AB10-50, а потім створили ряд поштових індексів між ними.

Щоразу, коли будується нова вулиця, створюється новий поштовий індекс. Це частина процесу отримання дозволу на будівництво; органи місцевого самоврядування зобов'язані постійно оновлювати це поштове відділення (не те, що вони роблять).

Крім того, як зазначає низка інших користувачів, є спеціальні поштові індекси, такі як Girobank, GIR 0AA та лист для Санти, SAN TA1 - ви, мабуть, не хочете нічого там публікувати, але це не здається будь-яка інша відповідь.

Потім з'являються поштові індекси BFPO, які тепер змінюються на більш стандартний формат . Обидва формати будуть дійсними. Нарешті, є закордонна територія джерела Вікіпедії .

+ ---------- + -------------------------------------- -------- +
| Поштовий індекс | Місцезнаходження |
+ ---------- + -------------------------------------- -------- +
| AI-2640 | Ангілья |
| ASCN 1ZZ | Острів Вознесіння |
| STHL 1ZZ | Свята Єлена |
| TDCU 1ZZ | Трістан да Кунья |
| BBND 1ZZ | Британська територія Індійського океану |
| BIQQ 1ZZ | Британська територія Антарктики |
| FIQQ 1ZZ | Фолклендські острови |
| GX11 1AA | Гібралтар |
| PCRN 1ZZ | Острови Піткерн |
| SIQQ 1ZZ | Південна Джорджія та Південні Сандвічеві острови |
| TKCA 1ZZ | Острови Теркс і Кайкос |
+ ---------- + -------------------------------------- -------- +

Далі ви повинні врахувати, що Великобританія "експортувала" свою систему поштових індексів у багато місць у світі. Все, що підтверджує поштовий індекс "Великобританія", також підтвердить поштові індекси ряду інших країн.

Якщо ви хочете перевірити поштовий індекс у Великобританії, найбезпечніший спосіб зробити це - скористатися пошуком поточних поштових індексів. Існує ряд варіантів:

  • Ordnance Survey випускає Code-Point Open під ліцензією відкритих даних. Це буде дещо відставати від часів, але це безкоштовно. Це (мабуть - я не можу пригадати) не включатиме північно-ірландські дані, оскільки в опитуванні ордерів немає жодної місії. Картографування в Північній Ірландії проводиться опитуванням Ordnance північної Ірландії, і вони мають свій окремий платний продукт Pointer . Ви можете використати це та додати декілька, які не охоплені досить легко.

  • Royal Mail випускає файл адресного файла з поштовим індексом (PAF) , сюди входить BFPO, що я не впевнений, що робить Code-Point Open. Він оновлюється регулярно, але коштує грошей (і вони іноді можуть прямо сказати про це). PAF включає повну адресу, а не лише поштові індекси та постачається із власним Посібником програмістів . Наразі група користувачів відкритих даних (ODUG) лобіює звільнення PAF безкоштовно, ось опис їхньої позиції .

  • Нарешті, є AddressBase . Це співпраця між Ordnance Survey, місцевими органами влади, Royal Mail та відповідною компанією для створення остаточного каталогу всієї інформації про всі адреси Великобританії (вони також були досить успішними). Це платно, але якщо ви працюєте з місцевою владою, урядовим департаментом чи державною службою, вони можуть безкоштовно використовувати їх. Тут набагато більше інформації, ніж включені лише поштові індекси.


погляд вгору звучить цікаво
SuperUberDuper

2
хоча це не відповідь, яку шукала оп, це, мабуть, найкорисніше. Це спонукає мене розслабити правила перевірки, які я збираюся робити.
Джон Хант

22

Я переглянув деякі відповіді вище, і рекомендую не використовувати шаблон із відповіді @ Dan (приблизно 15 грудня 10 р.) , Оскільки він неправильно позначає майже 0,4% дійсних поштових індексів як недійсні, в той час як інші не .

Ordnance Survey надає послугу під назвою Code Point Open, яка:

містить перелік усіх поточних одиниць поштового індексу у Великобританії

Я порівнював кожен з вищевказаних регексів по повному списку поштових індексів (6 липня '13) з цих даних, використовуючи 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"

Всього існує 1686 202 поштових індекси.

Нижче наведено номери дійсних поштових індексів, які не відповідають кожному $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

Звичайно, ці результати стосуються лише дійсних поштових індексів, неправильно позначених як недійсні. Так:

'^.*$'
# => 0

Я нічого не кажу про те, яка модель є найкращою щодо фільтрації недійсних поштових індексів.


1
Хіба це не те, що я говорю у своїй відповіді, і якщо ви їдете по неприйнятному маршруту, ви, мабуть, повинні зробити їх усі, і постійно оновлювати його, якщо хтось змінить свою відповідь? Якщо ні, то принаймні вкажіть дату останнього редагування відповіді, яку ви отримали, щоб люди могли побачити, чи змінилася вона з тих пір.
Бен

Справедливий пункт. Відредаговано відповідно. Я думаю, що це додає до дискусії, щоб зазначити, що більшість із цих моделей не виключає жодного коду СРО, але це найбільше відповідь (дійсний регулярний вираз). Майбутні читачі: майте на увазі, що мої результати, ймовірно, застаріли.
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)$

Регулярне вираження, щоб відповідати дійсним поштовим індексам Великобританії. У поштовій системі Великобританії не всі листи використовуються у всіх положеннях (те саме, що мають реєстраційні знаки транспортних засобів), і для цього є різні правила. Цей регекс враховує ці правила. Деталі правил: Перша половина поштового індексу Дійсні формати [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] Позиція винятків - Перша. Контракт - QVX не використовується Позиція - Друге. Контракт - IJZ не використовується, за винятком позиції GIR 0AA - Третя. Обмеження - AEHMNPRTVXY використовується лише положення - Forth. Контрагент - ABEHMNPRVWXY Друга половина поштового індексу Дійсні формати [0-9] [AZ] [AZ] Позиція винятків - друга та третя. Контрагент - CIKMOV не використовується

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


1
Поняття не маю, чому люди спростували цю відповідь - це правильний вираз
Оллі,

Регекс не працює для поштових індексів "YO31" та "YO31 1" у Javscript.
Пратік Хадлоя

9
Я не думаю, що це правильно, оскільки наведений регулярний вираз суперечить опису, і ви припускаєте, що у вас можуть бути поштові індекси, починаючи з 0-9яких ви не можете
Луїджі Плінг

4
Цей регекс не працює на приблизно 6000 дійсних поштових індексах, тому я рекомендую проти нього. Дивіться мою відповідь .
RichardTowers

це не вдається на будь-якому поштовому індексі з малих літер або без місця для мене
Танцюрист

14

Відповідно до цієї таблиці Вікіпедії

введіть тут опис зображення

Ця закономірність охоплює всі випадки

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

При використанні його на Android \ Java використовуйте \\ d


Я вважав це найбільш читаною відповіддю, хоча він шукає лише форму поштового індексу, а не фактичні дійсні коди відповідно до рішень, які беруть інформацію з веб-сайту gov.uk, але це досить добре для мого використання. Трохи погравши з ним (у python), я створив його на трохи більш компактний, але еквівалентний регулярний вираз, який також дозволяє отримати необов'язковий простір: ([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})
Річард J

14

Більшість відповідей тут не працювали на всі поштові індекси, які я маю в своїй базі даних. Нарешті я знайшов той, який підтверджує всі, використовуючи новий вираз, наданий урядом:

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

Це не в жодній з попередніх відповідей, тому я публікую його тут, якщо вони знімають посилання:

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

ОНОВЛЕННЯ: оновлений регулярний вираз, як вказував Джеймі Булл. Не впевнений, чи це було моєю помилкою при копіюванні, чи це помилка в урядовому регексе, посилання зараз не працює ...

ОНОВЛЕННЯ: Як знайдено ctwheels, цей регулярний вимір працює з ароматом регулярного вираження javascript. Дивіться його коментар для одного, який працює з ароматом 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})$слід ^([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})$- помітити різницю ;-)
Джеймі Булл

1
Пляма на! Оновлено мою відповідь. Дякую!
Хесус Каррера

2
Це єдина відповідь тут, яка працювала в regexr.com та Notepad ++. Хоча я змінив його ([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})(видалив ^і $додав ?пробіл) для regexr.com, щоб знайти більше одного результату, і обидва знайти результат, у якому немає сепаратора пробілу.
mythofechelon

@ctwheels цей регулярний вираз призначений для аромату javascript. Якщо у вашому посиланні на помилку ви виберете javascript, він буде працювати. Це чудовий улов, і я оновлю свою відповідь.
Jesús Carrera

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})|(([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}))$є виправленим регулярним виразом.
ctwheels

12

Стара публікація, але все ще досить висока в результатах google, тому я подумав про оновлення. Цей документ 14 жовтня визначає регулярний вираз поштового індексу Великобританії як:

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

від:

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

Документ також пояснює логіку, що стоїть за ним. Однак він має помилку (закреслений жирним шрифтом), а також дозволяє використовувати малі регістри, що хоч легально не є звичайним, тому змінена версія:

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

Це працює з новими лондонськими поштовими індексами (наприклад, W1D 5LH), які не мали попередні версії.


Схоже, помилка, яку ви виділили жирним шрифтом, була виправлена ​​в документі, але я все ж вважаю за краще ваш регулярний вираз, оскільки його легше читати.
професор програмування

5
Єдине, що я б сказав, це зробити простір необов’язковим, змінивши пробіл на \ 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-9][A-Za-z]{2}))$є виправленим регулярним виразом.
ctwheels

10

Це регулярне вираження, яке Google подає до домену 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}

10

Поштові індекси можуть змінюватися, і єдиний вірний спосіб перевірки поштового індексу - це мати повний перелік поштових індексів і перевірити, чи він там є.

Але регулярні вирази корисні, оскільки вони:

  • прості у використанні та реалізації
  • короткі
  • швидко бігають
  • досить прості в обслуговуванні (порівняно з повним списком поштових індексів)
  • як і раніше вловлюють більшість вхідних помилок

Але регулярні вирази, як правило, важко підтримувати, особливо для тих, хто цього не придумав. Так має бути:

  • якомога легше зрозуміти
  • відносно майбутнє доказ

Це означає, що більшість регулярних виразів у цій відповіді недостатньо хороші. Наприклад, я можу побачити, що [A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRV-Y]буде відповідати області поштового індексу форми AA1A - але це буде біль у шиї, якщо і коли буде додано нову область поштового індексу, тому що важко зрозуміти, які області поштових індексів відповідають.

Я також хочу, щоб моє регулярне вираження відповідало першій та другій половині поштового коду як збіг у дужках.

Тому я придумав це:

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

У форматі PCRE його можна записати так:

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

Для мене це правильний баланс між максимальною валідацією, в той же час захищеною від майбутнього і забезпеченням легкого обслуговування.


Не впевнений, чому ви проголосували проти цього - це працює з усіма дійсними поштовими кодами, які я накинув на нього, і пробілами, на які багато з вищезазначених відповідей неправильно поводяться. Хтось би потурбував пояснити, чому?
Джон

1
@Jon Він також відповідає, коли інші символи додаються до початку або кінця, наприклад, aSW1A 1AAasfgдля мене відповідні (я не підкреслював, хоча, як здається, це можна легко виправити)
decvalts

9

Я шукав регекс поштового індексу у Великобританії останній день або близько того, і натрапив на цю тему. Я пропрацював більшу частину вищенаведених пропозицій, і жодна з них не працювала на мене, тому я придумав власний регекс, який, наскільки я знаю, фіксує всі дійсні поштові індекси у Великобританії станом на січень 13 року (згідно з останньою літературою з Королівська пошта).

Нижче розміщені регулярні вирази та деякі прості поштові інспектори PHP-коду. ПРИМІТКА: - Він дозволяє використовувати малі або великі поштові індекси та аномалію GIR 0AA, але мати справу з більш ніж ймовірним наявністю проміжку в середині введеного поштового індексу, він також використовує простий str_replace, щоб видалити простір перед тестуванням проти регексу. Будь-які розбіжності, окрім цього, і самі Королівська пошта навіть не згадують їх у своїй літературі (див. Http://www.royalmail.com/sites/default/files/docs/pdf/programmers_guide_edition_7_v5.pdf та починайте читати зі сторінки 17) !

Примітка. У власній літературі Royal Mail (посилання вище) є незначна неоднозначність навколо 3-ї та 4-ї позицій та винятки, якщо ці символи є літерами. Я зв’язався із Royal Mail безпосередньо, щоб очистити його та власними словами "Лист у 4-му положенні Зовнішнього коду у форматі AANA NAA не має винятків. Виключення з 3-ї позиції стосуються лише останньої літери Зовнішнього коду з формат ANA NAA. " Прямо з уст коня!

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

    }

?>

Я сподіваюся, що це допомагає будь-кому, хто натрапив на цю нитку, шукаючи рішення.


1
Мені буде цікаво дізнатись, які приклади поштових індексів не були опубліковані?
Джаф - Бен Дюгід

Я не можу надати вам конкретний поштовий індекс (не маючи доступу до повного списку PAF), але поштові індекси у форматі ANA NAA потенційно можуть вийти з ладу, оскільки літери P і Q дозволені на 3-й позиції, а поштові індекси у форматі AANA NAA потенційно також не вдається, оскільки 4-та позиція дозволяє всі літери (регулярний вираз, наведений у прийнятій відповіді вище, не враховує жодного з них). Як я кажу, я йду лише за поточною порадою від Королівської пошти - на момент відповіді вище, можливо, цей регекс повністю відповідав.
Dan Solo

Дякую за голову вгору - я можу бачити, що "P", як видається, було додано як прийнятне на третій позиції (від вашого зв’язаного документа), але не Q - але де ви читаєте, що "4-та позиція дозволяє всі літери"? Наскільки я бачу, документ не згадує "четверту позицію", тому я прочитав би її як "третю букву незалежно від фактичної позиції".
Джаф - Бен Дюгід

1
Щойно було слово з команди підтримки Royal Mail, і моє тлумачення правил, мабуть, правильне. Лист у 4-му положенні Зовнішнього коду (наприклад, AANA NAA) не має винятків, а винятки з 3-ї позиції стосуються лише останньої літери (наприклад, ANA NAA). Прямо з уст коня.
Dan Solo

1
@DanSolo Цей регекс поверне справжню відповідність для першої половини дійсного поштового індексу, у якому відсутній внутрішній код, наприклад, SW1Aабо BD25без другої половини (або принаймні для мене)
decvalts

7

Ось регулярний вираз на основі формату, визначеного в документах, пов'язаних з відповіддю до marcj:

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

Єдина відмінність між цим і специфікаціями полягає в тому, що останні 2 символи не можуть бути в [CIKMOV] відповідно до специфікацій.

Редагувати: Ось ще одна версія, яка перевіряє обмеження символів, що відкладаються.

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

Існує набагато більше складностей у поштовому індексі Великобританії, ніж просто прийняття A-Z- Qце ніколи не дозволено, Vвикористовується лише врядно і т. Д. Залежно від положення персонажа.
Джаф - Бен Дюгід

2
Це, мабуть, не має значення, якщо ви хочете - це перевірка синтаксису. Як зауважили багато інших, лише пошук у оновленій базі даних стає майже коректним, і навіть тоді виникає проблема того, наскільки оновлена ​​база даних. Отже, для мене ця синтаксична перевірка синтаксису є чіткою, простою та корисною.
Рік-777

5

Деякі з вищевказаних регексів трохи обмежуючі. Зверніть увагу на справжній поштовий індекс: "W1K 7AA" не вдасться, оскільки правило "Позиція 3 - AEHMNPRTVXY використовується тільки" вище, оскільки "K" буде заборонено.

регулярний вираз:

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

Здається трохи точніше, дивіться статтю у Вікіпедії під назвою "Поштові індекси у Сполученому Королівстві" .

Зауважте, що для цього регулярного вираження потрібні лише великі літери.

Більш важливим питанням є те, чи обмежуєте ви введення користувачем дозволити лише поштові індекси, які існують насправді, або ви просто намагаєтесь зупинити користувачів, щоб вони вводили повний сміття в поля форми. Грамотна відповідність усіх можливих поштових індексів та підтвердження їх майбутнього є складнішою загадкою, і, мабуть, не варто цього, якщо ви не HMRC.


Схоже, поштове відділення перейшло, але уряд дещо відстає :(
Джаф - Бен Дюгід

4
Я використовую це: "^ ([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}) $ "Мені це подобається, тому що він дозволяє використовувати верхній і нижній регістри і робить простір необов’язковим - краще для зручності використання, якщо не на 100% правильного!
bigtv

4

ось як ми мали справу з проблемою поштового індексу у Великобританії:

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

Пояснення:

  • очікуйте 1 або 2 az символів, верхнього або нижнього штрафу
  • очікуйте 1 або 2 числа
  • очікуйте 0 або 1 az char, верхній або нижній штраф
  • Додатковий простір дозволено
  • очікуємо 1 число
  • очікуйте 2 az, верхній або нижній штраф

Це отримує більшість форматів, потім ми використовуємо db, щоб перевірити, чи дійсний поштовий індекс, ці дані керуються відкритою точкою https://www.ordnancesurvey.co.uk/opendatadownload/products.html

сподіваюся, що це допомагає


Це дозволяє AANNA NAAнедійсний формат .
ctwheels

Отже, частина відповіді "Це отримує більшість форматів". :)
Алекс Стівенс

4

Основні правила:

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

Поштові індекси у Великобританії (або поштові індекси, як їх називають) складаються з п'яти-семи буквено-цифрових символів, розділених пробілом. Правила, які стосуються того, які персонажі можуть з’являтися на певних позиціях, є досить складними та загрожують винятками. Щойно показаний регулярний вираз дотримується основних правил.

Повні правила:

Якщо вам потрібен регулярний вираз, який позначає всі поля для правил поштового коду за рахунок читабельності, ось вам:

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

Джерело: https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9781449327453/ch04s16.html

Тестований на базі даних наших клієнтів і здається абсолютно точним.


4

Я використовую наступний регулярний вираз, який я перевірив на всіх дійсних поштових індексах Великобританії. Він ґрунтується на рекомендованих правилах, але стискається настільки, наскільки це розумно, і не використовує жодних спеціальних правил для регулярних виразів.

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

Він передбачає, що поштовий індекс був перетворений у великі регістри і не має провідних або кінцевих символів, але прийме необов'язковий пробіл між вихідним кодом та індексом.

Спеціальний поштовий індекс "GIR0 0AA" виключений і не підтверджується, оскільки його немає в офіційному списку поштових відділень поштових відділень, і, наскільки мені відомо, він не буде використовуватися як зареєстрована адреса. Додавання його має бути банальним як окремий випадок, якщо потрібно.


4

Я хотів простий регулярний вираз, де добре, щоб дозволити занадто багато, але не заперечувати дійсний поштовий індекс. Я пішов з цим (вхід - це викреслений / обрізаний рядок):

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

Це дозволяє отримати найкоротші можливі поштові індекси, такі як "L1 8JQ", а також найдовші, такі як "OL14 5ET".

Оскільки він дозволяє містити до 8 символів, він також дозволить отримати неправильні 8 символьних поштових індексів, якщо немає місця: "OL145ETX". Але знову ж таки, це спрощений підсумок, коли це досить добре.


О, мої вибачення Я думаю, що я пропустив те, коли я тестував вчора.
Іван

3

Перша половина поштового індексу Дійсні формати

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

Винятки
Позиція 1 - QVX не використовується
Позиція 2 - IJZ не використовується, за винятком положення GIR 0AA
Позиція 3 - AEHMNPRTVXY використовується лише
Позиція 4 - ABEHMNPRVWXY

Друга половина поштового індексу

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

Винятки
Позиція 2 + 3 - CIKMOV не використовується

Пам’ятайте, що не всі можливі коди використовуються, тому цей список є необхідною, але недостатньою умовою для дійсного коду. Можливо, буде легше співставити список усіх дійсних кодів?


3

Щоб перевірити поштовий індекс у правильному форматі, відповідно до посібника програміста 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})$

Всі поштові індекси на doogal.co.uk збігаються, крім тих, які вже не використовуються.

Додайте ?пробіл після використання пробілу та використовуйте невідчутну до регістру відповідність на це запитання:

'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

Цей варіант дозволяє порожні пробіли та вкладки з обох сторін у випадку, якщо ви не хочете провалити перевірку, а потім обрізати її відрізати стороною.

^\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*$)

Це єдиний шаблон, який працював для мене за допомогою c # (System.Text.RegularExpressions) із прикладами, описаними в оригінальному запитанні
MattjeS

Це невдалий вираз уряду Великобританії, і він не підтверджує деякі допустимі формати.
ctwheels

@ctwheels Привіт, ви можете, будь ласка, надати невдалий поштовий індекс, дякую.
Матас Вайткевічус

Наприклад AAA 1AA, невірний формат: див. Мою відповідь для пояснення та виправлення.
ctwheels

2

Щоб додати до цього списку більш практичний регулярний вираз, який я використовую, що дозволяє користувачеві вводити 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}))$

Цей регулярний вираз дозволяє використовувати великі і малі літери з додатковим пробілом між ними

З точки зору розробників програмного забезпечення, цей регекс корисний для програмного забезпечення, де адреса може бути необов’язковою. Наприклад, якщо користувач не хотів надавати свої адреси адреси


1

Подивіться на код python на цій сторінці:

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

У мене є якийсь розбір поштових індексів. Вимога досить проста; Я повинен розібрати поштовий індекс у вихідний код і (необов'язково). Хорошим новим є те, що мені не потрібно проводити жодної перевірки - я просто повинен рубати те, що мені було надано, розпливчасто. Я не можу припустити багато щодо свого імпорту з точки зору форматування, тобто з регістру та вбудованих пробілів. Але це не погана новина; погана новина полягає в тому, що я повинен все це робити в RPG. :-(

Тим не менш, я кинув трохи функції Python разом, щоб уточнити своє мислення.

Я використовував його для обробки поштових індексів для мене.


1

Нам дали специфікацію:

Поштові індекси у Великобританії мають бути в одній з таких форм (за одним винятком, див. Нижче): 
    § A9 9AA 
    § A99 9AA
    § AA9 9AA
    § AA99 9AA
    § A9A 9AA
    § AA9A 9AA
де А являє алфавітний символ, а 9 являє собою числовий символ.
До алфавітних символів застосовуються додаткові правила:
    § Символ у позиції 1 може бути не Q, V або X
    § Символом у позиції 2 може бути не I, J або Z
    § Символом у позиції 3 може бути не I, L, M, N, O, P, Q, R, V, X, Y або Z
    § Символ у позиції 4 може бути не C, D, F, G, I, J, K, L, O, Q, S, T, U або Z
    § Символи, які знаходяться в правій правій двох позиціях, не можуть бути C, I, K, M, O або V
Єдиним винятком, який не дотримується цих загальних правил, є поштовий індекс "GIR 0AA", який є спеціальним дійсним поштовим індексом.

Ми придумали це:

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

Але зверніть увагу - це дозволяє будь-яку кількість пробілів між групами.


2
paulslater19, на жаль, ваше рішення дозволяє поштові індекси A99A 9AA.

1

У мене є регекс для перевірки поштового індексу Великобританії.

Це працює для всіх типів поштового індексу, як внутрішнього, так і зовнішнього

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

Це працює для всіх типів формату.

Приклад:

AB10 --------------------> ТІЛЬКИ ВНУТРІШНІ ПОСТКОД

A1 1AA ------------------> КОМБІНАЦІЯ ПОСТКОДУ (ВНУТРІШНЯ І ВНУТРІШНЯ)

WC2A --------------------> зовнішній


1

Прийнята відповідь відображає правила, надані Royal Mail, хоча в регулярному виразі є помилка друку. Схоже, цей друк був там і на сайті gov.uk (як це є на сторінці архіву XML).

У форматі A9A 9AA правила дозволяють символу P на третьому положенні, тоді як регулярний вираз відключає це. Правильним регулярним виразом було б:

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

Скорочення цього призводить до наступного регулярного вираження (для якого використовується синтаксис 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})

Він також включає необов'язковий простір між першим і другим блоком.


1

Що я знайшов у майже всіх варіаціях, а також регулярний вираз з pdf-файлу для масового перенесення та те, що є на веб-сайті вікіпедії, це таке, спеціально для регексу wikipedia є, після першого | (вертикальної смуги) повинно бути ^. Я зрозумів це, перевіривши на AA9A 9AA, тому що в іншому випадку перевірка формату для A9A 9AA підтвердить його. Для прикладу перевірка наявності EC1D 1BB, яка повинна бути недійсною, повертається дійсною, оскільки C1D 1BB є допустимим форматом.

Ось що я придумав для хорошого регулярного виразу:

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

За допомогою емпіричного тестування та спостереження, а також підтвердження за допомогою https://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom#Validation , ось моя версія регексу Python, який правильно аналізує та підтверджує поштовий індекс у Великобританії:

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

Цей регулярний вираз є простим і має групи захоплення. Він не включає всі перевірки законних поштових індексів Великобританії, але враховує лише позиції літери та цифри.

Ось як я би використовував це в коді:

@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

Ось одиничні тести:

@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

Мені була потрібна версія, яка буде працювати в SAS з 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}$

Тестові приклади та примітки:

/* 
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

Нижче метод перевірить поштовий індекс та надасть повну інформацію

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!"}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.