RegEx для сопоставления почтовых индексов Великобритании - PullRequest
158 голосов
/ 03 октября 2008

Мне нужно регулярное выражение, которое будет проверять полный комплексный почтовый индекс Великобритании только во входной строке Все необычные формы почтовых индексов должны быть покрыты так же, как и обычные. Например:

Спички

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

Нет совпадений

  • aWC2H 7LT
  • WC2H 7LTa
  • WC2H

Как мне решить эту проблему?

Ответы [ 30 ]

10 голосов
/ 30 апреля 2014

Почтовые индексы могут быть изменены, и единственный верный способ проверить почтовый индекс - это иметь полный список почтовых индексов и посмотреть, есть ли он там.

Но регулярные выражения полезны, потому что они:

  • просты в использовании и реализации
  • короткие
  • быстро запустить
  • довольно прост в обслуживании (по сравнению с полным списком почтовых индексов)
  • по-прежнему перехватывает большинство ошибок ввода

Но регулярные выражения, как правило, трудно поддерживать, особенно для тех, кто их не придумал. Так должно быть:

  • настолько легко понять, насколько это возможно
  • относительно будущее

Это означает, что большинство регулярных выражений в этом ответе недостаточно хороши. Например. Я вижу, что [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

Для меня это правильный баланс между проверкой в ​​максимально возможной степени, но в то же время перспективой и возможностью легкого обслуживания.

9 голосов
/ 10 января 2013

Я искал регулярное выражение почтового индекса в Великобритании последний день или около того и наткнулся на эту тему. Я работал над большинством приведенных выше предложений, и ни одно из них не сработало для меня, поэтому я пришел к своему собственному регулярному выражению, которое, насколько я знаю, фиксирует все действительные почтовые индексы Великобритании по состоянию на январь 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-й позиции применяются только к последней букве Исходящего кода с Формат АНА НАА. " Прямо изо рта лошади!

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

    }

?>

Я надеюсь, что это поможет любому, кто сталкивается с этой темой, ищет решение.

7 голосов
/ 08 июня 2011

Вот регулярное выражение, основанное на формате, указанном в документах, которые связаны с ответом Марджа:

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

Единственная разница между этим и спецификациями состоит в том, что последние 2 символа не могут быть в [CIKMOV] согласно спецификациям.

Edit: Вот еще одна версия, которая проверяет наличие ограничений на конечные символы.

/^[A-Z]{1,2}[0-9][0-9A-Z]? ?[0-9][A-BD-HJLNP-UW-Z]{2}$/
5 голосов
/ 25 января 2011

Некоторые из приведенных выше регулярных выражений немного ограничены. Обратите внимание на подлинный почтовый индекс: «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 голосов
/ 23 января 2015

Основные правила:

^[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 голосов
/ 09 ноября 2015

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

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

Предполагается, что почтовый индекс был преобразован в верхний регистр и не имеет начальных или конечных символов, но примет необязательный пробел между исходящим кодом и incode.

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

3 голосов
/ 03 октября 2008

Первая половина почтового индекса. Допустимые форматы

  • [A-Z] [A-Z] [0-9] [A-Z]
  • [A-Z] [A-Z] [0-9] [0-9]
  • [A-Z] [0-9] [0-9]
  • [A-Z] [A-Z] [0-9]
  • [A-Z] [A-Z] [A-Z]
  • [A-Z] [0-9] [A-Z]
  • [A-Z] [0-9]

Исключения
Положение 1 - QVX не используется
Позиция 2 - IJZ не используется, за исключением GIR 0AA
Позиция 3 - используется только AEHMNPRTVXY
Положение 4 - ABEHMNPRVWXY

Вторая половина почтового индекса

  • [0-9] [A-Z] [A-Z]

Исключения
Позиция 2 + 3 - CIKMOV не используется

Помните, что используются не все возможные коды, поэтому этот список является необходимым, но не достаточным условием для действительного кода. Может быть проще сопоставить список всех допустимых кодов?

3 голосов
/ 27 марта 2015

Чтобы проверить почтовый индекс в допустимом формате согласно Руководству программиста 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 голосов
/ 07 августа 2014

вот как мы работаем с проблемой почтового индекса в Великобритании:

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

Пояснение:

  • ожидайте 1 или 2 символа a-z, верхний или нижний штраф
  • ожидайте 1 или 2 числа
  • ожидайте 0 или 1 символ a-z, верхний или нижний штраф
  • необязательный пробел разрешен
  • ожидаем 1 число
  • ожидайте 2 a-z, верхний или нижний штраф

Получается большинство форматов, затем мы используем базу данных, чтобы проверить, является ли почтовый индекс реальным, эти данные управляются openpoint https://www.ordnancesurvey.co.uk/opendatadownload/products.html

надеюсь, это поможет

3 голосов
/ 01 декабря 2017

Я хотел простое регулярное выражение, где можно разрешить слишком много, но не запретить действительный почтовый индекс. Я пошел с этим (вход является обрезанной / обрезанной строкой):

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

Длина от 5 до 7 (без учета пробелов) означает, что мы допускаем как можно более короткие почтовые индексы, такие как «L1 8JQ», так и самые длинные, такие как «OL14 5ET».

РЕДАКТИРОВАТЬ: изменил 8 на 7, чтобы мы не допускали 8-символьные почтовые индексы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...