RegEx для сопоставления почтовых индексов Великобритании

186

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

Спички

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

Не совпадает

  • AWC2H 7LT
  • WC2H 7LTa
  • WC2H

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

Киран Бентон
источник
2
@axrwkr, который не выглядит полезным
Киран Бентон
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/…
Стивен Кейбл
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), и они предоставляют более строгий тест, который вы можете попробовать.

Brian Campbell
источник
52
И это reg ex с необязательным пробелом между двумя сегментами (GIR 0AA) | ((([AZ- [QVX]] [0-9] [0-9]?) | (([AZ- [QVX]] [AZ- [IJZ]] [0-9] [0-9]) |? (([AZ- [QVX]] [0-9] [А-HJKSTUW]) | ([AZ- [QVX]] [ AZ- [IJZ]] [0-9] [ABEHMNPRVWXY])))) \ s? [0-9] [AZ- [CIKMOV]] {2})
gb2d
7
Это может быть хорошей идеей, чтобы привести фактическое регулярное выражение в ответ, так как страницы, кажется, истекает каждый год ...
pauloya
7
Обратите внимание, что это регулярное выражение предназначено для XML-схемы, которая, очевидно, немного отличается от других разновидностей регулярных выражений
artbristol
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})$, что является слегка измененной версией, предложенной Minglis выше.

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

После некоторых исследований мы нашли еще немного информации. По-видимому, страница на govtalk.gov.uk указывает на спецификацию почтовых индексов govtalk-postcodes . Это указывает на схему 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}))$

Это не распространяется на заморские территории, а только обеспечивает соблюдение формата, а НЕ на существование различных областей. Он основан на следующих правилах:

Может принимать следующие форматы:

  • «ГИР 0АА»
  • A9 9ZZ
  • A99 9ZZ
  • AB9 9ZZ
  • AB99 9ZZ
  • A9C 9ZZ
  • AD9E 9ZZ

Куда:

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

С наилучшими пожеланиями

Colin

Colin
источник
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,}вместо *неограниченных, необязательных пробелов?
Код животных
76

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

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


Заметка

Мой ответ (и регулярные выражения в целом):

  • Проверяет только форматы почтовых индексов .
  • Не гарантирует, что почтовый индекс законно существует .
    • Для этого используйте соответствующий API! Смотрите ответ Бена для получения дополнительной информации.

Если вас не интересует плохое регулярное выражение, и вы просто хотите пропустить ответ, прокрутите вниз до раздела « Ответ ».

Плохое регулярное выражение

Регулярные выражения в этом разделе не должны использоваться.

Это ошибочное регулярное выражение, которое правительство Великобритании предоставило разработчикам (не уверен, как долго будет действовать эта ссылка, но вы можете увидеть это в их документации 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})$

Проблемы

Проблема 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. Исправление регулярного выражения правительства Великобритании ):

Смотрите регулярное выражение в использовании здесь .

^([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#(где #представляет число), они считаются необязательными альтернативными почтовыми индексами . Эти почтовые индексы следуют (ed) формат BFPO, за которым следуют 1-4 цифры:

Смотрите регулярное выражение в использовании здесь

^BFPO ?\d{1,4}$

3.3 Санта?

Есть еще один особый случай с Сантой (как уже упоминалось в других ответах): SAN TA1это действительный почтовый индекс. Регулярное выражение для этого очень просто:

^SAN ?TA1$
ctwheels
источник
4
Упрощенные шаблоны - действительно хороший вариант для использования. Я считаю, что лучше не ограничивать регулярные выражения, так как вам необходимо убедиться, что они обновлены с любыми изменениями, иначе у вас могут быть очень злые пользователи. Я считаю, что лучше сопоставить с упрощенным регулярным выражением, чтобы отсеять очевидные ошибки, а затем применить дополнительные проверки, такие как поиск адреса (или подтверждение по электронной почте в случае регулярного выражения электронной почты), чтобы подтвердить достоверность.
Джеймс Койл
2
Отличный и тщательный анализ.
Стив
1
Блестящий ответ на многих уровнях. В конце концов, я пошел по вашему второму упрощенному шаблону. Поскольку у меня фактически есть БД со всеми почтовыми индексами Великобритании, мне просто нужен первый проход, чтобы увидеть, может ли строка адреса содержать действительный почтовый индекс, так что мне нет дела до ложных срабатываний (так как фактический поиск искоренит их) Но я забочусь о ложных негативах. И скорость также имеет значение.
Джон Пауэлл
Существует так много проблем с системой почтовых индексов Великобритании, которая была явно создана комитетом еще до компьютерной эры, но проблема переменной длины и пробелов является одной из самых пагубных. Я видел всевозможные ужасы, включая дополнительные почтовые индексы, такие как E1 5JX - E1 5JX, т. Е. С тремя пробелами, так что он прекрасно совмещается с SW18 5HA в Excel (вставьте ужасно неподходящее программное обеспечение для управления адресами). ИМХО, единственное разумное решение - убрать все пробелы, чтобы почтовый индекс представлял собой одну строку, прежде чем он достигнет Elastic, Solr, Postgres и т. Д.
Джон Пауэлл,
45

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

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

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

Всякий раз, когда строится новая улица, создается новый почтовый индекс. Это часть процесса получения разрешения на строительство; местные власти обязаны держать это в курсе с почтовым отделением (не то, что они все делают).

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

Затем есть почтовые индексы BFPO, которые теперь меняются на более стандартный формат . Оба формата будут действительны. Наконец, есть источник Wikipedia заморских территорий .

+ ---------- + -------------------------------------- -------- +
| Почтовый индекс | Расположение |
+ ---------- + -------------------------------------- -------- +
| 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 под лицензией открытых данных. Это будет немного отставать от времени, но это бесплатно. Это (вероятно, я не помню) не будет включать данные по Северной Ирландии, так как Обследование артиллерийских орудий там не имеет никакого отношения. Картографирование в Северной Ирландии проводится Картографическим управлением Северной Ирландии, и у них есть отдельный платный продукт Pointer . Вы можете использовать это и добавить те, которые не покрываются достаточно легко.

  • Royal Mail выпускает адресный файл почтового индекса (PAF) , в том числе BFPO, но я не уверен, что Code-Point Open делает. Он регулярно обновляется, но стоит денег (и они могут быть откровенно плохими). PAF содержит полный адрес, а не только почтовые индексы, и поставляется с собственным Руководством для программистов . Open User User Group (ODUG) в настоящее время лоббирует выпуск PAF бесплатно, вот описание их позиции .

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

Бен
источник
поиск звучит интересно
SuperUberDuper
2
Хотя это не тот ответ, который искал опера, он, вероятно, наиболее полезен. Это побудит меня ослабить правила проверки, которые я собираюсь сделать.
Джон Хант
22

Я посмотрел некоторые из приведенных выше ответов, и я бы рекомендовал не использовать шаблон из ответа @ Dan (c. 15 декабря 2010 г.) , поскольку он неправильно помечает почти 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"

Всего насчитывается 1 686 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

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

RichardTowers
источник
1
Разве это не то, что я говорю в своем ответе, и если вы идете по пути опровержения, вам, вероятно, следует сделать их все и держать его в курсе, если кто-то изменит свой ответ? Если нет, то, по крайней мере, укажите дату последнего редактирования ответа, из которого вы его взяли, чтобы люди могли видеть, было ли оно изменено с тех пор.
Бен
Честная оценка. Отредактировано соответственно. Я думаю, что это добавляет к обсуждению то, что большинство из этих шаблонов не исключают ни один из кодов CPO, но это делает ответ с наибольшим количеством голосов (действительное регулярное выражение). Будущие читатели: знайте, что мои результаты могут быть устаревшими.
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] [AZ] [0-9] [AZ] [AZ] [0-9] Исключения Позиция - Первая. Ограничение - QVX не используется Положение - Второе. Ограничение - IJZ не используется, кроме как в позиции GIR 0AA - третье. Ограничение - AEHMNPRTVXY используется только Position - 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
это не удается для любого почтового индекса в нижнем регистре или без пробела для меня
Dancer
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

AntPachon
источник
Я нашел этот ответ наиболее читабельным, хотя он ищет только форму почтового индекса, а не фактические действительные коды в соответствии с решениями, которые берут информацию с веб-сайта 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})
Ричард Дж
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, чтобы найти более одного результата, а для обоих - для результата, который не имеет разделителя пробелов.
Мифофешелон
@ctwheels это регулярное выражение для аромата javascript. Если ваша ссылка не указана, вы выбираете javascript, она будет работать. Это отличный улов, и я обновлю свой ответ.
Хесус Каррера
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), которых не было в предыдущих версиях.

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

<?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-я позиция разрешает все буквы (регулярное выражение, данное в принятом ответе выше, не учитывает ни одну из них). Как я уже сказал, я следую только текущему совету Королевской Почты - во время ответа выше, возможно, это регулярное выражение было полностью совместимым.
Дэн Соло
Спасибо за заголовки - я вижу, что "P", кажется, был добавлен как приемлемый в третьей позиции (из вашего связанного документа), но не Q - но где вы читаете, что "4-я позиция разрешает все буквы"? Насколько я вижу, в документе нет четкого упоминания о "четвертой позиции", поэтому я бы прочитал это как "третье письмо независимо от фактической позиции".
Жаф - Бен Дугуид
1
Я только что получил сообщение от службы поддержки Royal Mail, и моя интерпретация правил, по-видимому, верна. Буква в 4-й позиции внешнего кода (например, AANA NAA) не имеет исключений, а исключения 3-й позиции применяются только к последней букве (например, ANA NAA). Прямо изо рта лошади.
Дэн Соло,
1
@DanSolo Это регулярное выражение будет возвращать истинное совпадение для первой половины действительного почтового индекса без внутреннего кода, например, SW1Aили BD25без второй половины (или, по крайней мере, для меня)
декальты
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
Это может не иметь значения, если вам нужна проверка синтаксиса. Как отмечали многие другие, только поиск в современной базе данных становится почти правильным, и даже в этом случае возникает проблема того, насколько актуальна база данных. Итак, для меня это регулярное выражение проверки синтаксиса понятно, просто и полезно.
Rick-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.

minglis
источник
Похоже, почта пошла дальше, но правительство несколько отстает :(
Жаф - Бен Дугид
4
Я использую это: "^ ([Gg] [Ii] [Rr] 0 [Aa] {2}) | ((([A-Za-z] [0-9] {1,2}) | (( [A-Za-Z] [A-Ha-HJ-YJ-у] [0-9] {1,2}) | (([A-Za-Z] [0-9] [A-Za-г ]) | ([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 аз-чара, верхний или нижний штраф
  • ожидать 1 или 2 числа
  • ожидайте 0 или 1 аз символ, верхний или нижний штраф
  • разрешено дополнительное пространство
  • ожидать 1 число
  • ожидать 2 аз, верхний или нижний штраф

Это получает большинство форматов, затем мы используем базу данных, чтобы проверить, является ли почтовый индекс реальным, эти данные определяются открытой точкой 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

Проверено на базе данных наших клиентов и выглядит совершенно точно.

Raphos
источник
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})

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

Специальный почтовый индекс "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}))$

Это регулярное выражение позволяет использовать заглавные и строчные буквы с необязательным пробелом между

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

user1
источник
1

Посмотрите на код Python на этой странице:

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

Я должен разобрать почтовый индекс. Требование довольно простое; Я должен разобрать почтовый индекс в outcode и (необязательно) incode. Хорошая новость заключается в том, что мне не нужно выполнять какую-либо проверку - мне просто нужно разобрать то, что мне было предоставлено, в смутной форме. Я не могу предположить много о моем импорте с точки зрения форматирования, то есть регистра и встроенных пробелов Но это не плохие новости; Плохая новость в том, что я должен делать все это в RPG. :-(

Тем не менее, я добавил маленькую функцию Python, чтобы прояснить свое мышление.

Я использовал его для обработки почтовых индексов для меня.

Рудигер Вольф
источник
1

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

Почтовые индексы Великобритании должны быть в одной из следующих форм (с одним исключением, см. Ниже): 
    § A9 9AA 
    § A99 9AA
    § AA9 9AA
    § AA99 9AA
    § A9A 9AA
    § AA9A 9AA
где A представляет буквенный символ, а 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

Но обратите внимание - это позволяет любое количество пробелов между группами.

paulslater19
источник
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 --------------------> ВНЕШНИЙ

Swift-Master
источник
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})

Он также включает в себя необязательный пробел между первым и вторым блоком.

Stieb
источник
1

То, что я нашел почти во всех вариациях и регулярном выражении из pdf для массового переноса, и то, что находится на сайте википедии, таково, особенно для регулярного выражения википедии, должен быть ^ после первого | (вертикальная черта). Я понял это, протестировав 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)
jontsai
источник
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;
user667489
источник
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!"}
Aathi
источник