Проверка почтового индекса Соединенного Королевства (GB) без регулярного выражения

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

Поиск в Интернете, Wikipedia и SO, я мог найти только решения для проверки регулярных выражений.

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

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

Изменить: Чтобы помочь будущим посетителям и не давать вам больше размещать регулярные выражения, вот регулярное выражение, которое я тестировал ( начиная с 2013-04-24 ), чтобы работать для всех почтовых кодов в Code Point ( см. Ответ @Mikkel Løkke ):

//PHP PCRE (it was on Wikipedia, it isn't there anymore; I might have modified it, don't remember). $strPostalCode=preg_replace("/[\s]/", "", $strPostalCode); $bValid=preg_match("/^(GIR 0AA)|(((A[BL]|B[ABDHLNRSTX]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[HNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTY]?|T[ADFNQRSW]|UB|W[ADFNRSV]|YO|ZE)[1-9]?[0-9]|((E|N|NW|SE|SW|W)1|EC[1-4]|WC[12])[A-HJKMNPR-Y]|(SW|W)([2-9]|[1-9][0-9])|EC[1-9][0-9])[0-9][ABD-HJLNP-UW-Z]{2})$/i", $strPostalCode); 

Solutions Collecting From Web of "Проверка почтового индекса Соединенного Королевства (GB) без регулярного выражения"

Я пишу этот ответ на основе вики-страницы .

При проверке части валидации кажется, что существует 6 типов форматов (A = буква и 9 = цифра):

 AA9A 9AA AA9A9AA AA9A9AA A9A 9AA Removing space A9A9AA order it AA999AA A9 9AA ------------------> A99AA -------------> AA99AA A99 9AA A999AA A9A9AA AA9 9AA AA99AA A999AA AA99 9AA AA999AA A99AA 

Как мы видим, длина может варьироваться от 5 до 7, и мы должны учитывать некоторые особые случаи, если хотим.

Таким образом, функция, которую мы кодируем, должна сделать следующее:

  1. Удалите пробелы и преобразуйте их в верхний регистр (или в нижний регистр).
  2. Проверьте, является ли вход исключением, если он должен вернуть действительный
  3. Проверьте, соответствует ли длина ввода 4 < длина < 8.
  4. Проверьте, является ли он действительным почтовым индексом.

Последняя часть сложна, но мы разделим ее на три секции по длине для некоторого обзора:

  1. Длина = 7: AA9A9AA и AA999AA
  2. Длина = 6: AA99AA , A9A9AA и A999AA
  3. Длина = 5: A99AA

Для этого мы будем использовать switch() . Отныне это вопрос проверки персонажа по характеру, если это письмо или номер в нужном месте.

Итак, давайте посмотрим на нашу реализацию PHP:

 function check_uk_postcode($string){ // Start config $valid_return_value = 'valid'; $invalid_return_value = 'invalid'; $exceptions = array('BS981TL', 'BX11LT', 'BX21LB', 'BX32BB', 'BX55AT', 'CF101BH', 'CF991NA', 'DE993GG', 'DH981BT', 'DH991NS', 'E161XL', 'E202AQ', 'E202BB', 'E202ST', 'E203BS', 'E203EL', 'E203ET', 'E203HB', 'E203HY', 'E981SN', 'E981ST', 'E981TT', 'EC2N2DB', 'EC4Y0HQ', 'EH991SP', 'G581SB', 'GIR0AA', 'IV212LR', 'L304GB', 'LS981FD', 'N19GU', 'N811ER', 'NG801EH', 'NG801LH', 'NG801RH', 'NG801TH', 'SE18UJ', 'SN381NW', 'SW1A0AA', 'SW1A0PW', 'SW1A1AA', 'SW1A2AA', 'SW1P3EU', 'SW1W0DT', 'TW89GS', 'W1A1AA', 'W1D4FA', 'W1N4DJ'); // Add Overseas territories ? array_push($exceptions, 'AI-2640', 'ASCN1ZZ', 'STHL1ZZ', 'TDCU1ZZ', 'BBND1ZZ', 'BIQQ1ZZ', 'FIQQ1ZZ', 'GX111AA', 'PCRN1ZZ', 'SIQQ1ZZ', 'TKCA1ZZ'); // End config $string = strtoupper(preg_replace('/\s/', '', $string)); // Remove the spaces and convert to uppercase. $exceptions = array_flip($exceptions); if(isset($exceptions[$string])){return $valid_return_value;} // Check for valid exception $length = strlen($string); if($length < 5 || $length > 7){return $invalid_return_value;} // Check for invalid length $letters = array_flip(range('A', 'Z')); // An array of letters as keys $numbers = array_flip(range(0, 9)); // An array of numbers as keys switch($length){ case 7: if(!isset($letters[$string[0]], $letters[$string[1]], $numbers[$string[2]], $numbers[$string[4]], $letters[$string[5]], $letters[$string[6]])){break;} if(isset($letters[$string[3]]) || isset($numbers[$string[3]])){ return $valid_return_value; } break; case 6: if(!isset($letters[$string[0]], $numbers[$string[3]], $letters[$string[4]], $letters[$string[5]])){break;} if(isset($letters[$string[1]], $numbers[$string[2]]) || isset($numbers[$string[1]], $letters[$string[2]]) || isset($numbers[$string[1]], $numbers[$string[2]])){ return $valid_return_value; } break; case 5: if(isset($letters[$string[0]], $numbers[$string[1]], $numbers[$string[2]], $letters[$string[3]], $letters[$string[4]])){ return $valid_return_value; } break; } return $invalid_return_value; } 

Обратите внимание, что я не добавил британские почтовые отделения и негеографические коды .

Применение:

 echo check_uk_postcode('AE3A 6AR').'<br>'; // valid echo check_uk_postcode('Z9 9BA').'<br>'; // valid echo check_uk_postcode('AE3A6AR').'<br>'; // valid echo check_uk_postcode('EE34 6FR').'<br>'; // valid echo check_uk_postcode('A23A 7AR').'<br>'; // invalid echo check_uk_postcode('A23A 7AR').'<br>'; // invalid echo check_uk_postcode('WA3334E').'<br>'; // invalid echo check_uk_postcode('A2 AAR').'<br>'; // invalid 

Как предоставлено правительством Великобритании.

  (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])))) [0-9][AZ-[CIKMOV]]{2}) 

Я построил в Лондоне только почтовые программы, используя почтовые индексы, которые я получил от ЗДЕСЬ . Но, честно говоря, даже с лондонскими почтовыми индексами вам нужно гораздо больше места, чем необходимо. Конечно, идея тривиальна.

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

Если мини-распределенное обслуживание звучит как более эффективное решение, чем регулярное выражение, пойдите для него, но я уверен, что это не так. Если вам не нужны геопространственные запросы ваших собственных данных к британским почтовым индексам или тому подобное, я сомневаюсь, что хранилище DB является приемлемым решением. Только мои 2 цента.

Обновить

Согласно этому индексу, в Великобритании насчитывается 1 758 417 почтовых индексов. Я могу сказать, что я использую несколько кластеров Mongo (Amazon EC2 High Memory Instances), чтобы обеспечить надежные услуги только для Лондона (индексирование только лондонских почтовых индексов), и это довольно дорого, даже с базовым хранилищем.

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

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

Я смотрю на ссылку «Почтовые индексы в Соединенном Королевстве» в Википедии прямо сейчас.

http://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom

В разделе «Проверка» перечислены шесть форматов с комбинацией букв и цифр. Затем в примечаниях ниже есть дополнительная информация. Первое, что я попробую, это грамматика типа BNF с помощью инструмента, такого как GoldParserBuilder. Вы можете описать базовые форматы в более читаемом формате, при этом автоматически создаются эффективный парсер и лексер. Раньше я успешно использовал такие инструменты, чтобы избежать написания огромных, уродливых регулярных выражений.

С этого момента программа имеет правильно отформатированный почтовый индекс известного типа. На данный момент конкретные цифры или буквы могут что-то нарушить. Каждый тип почтового индекса может иметь функцию, запрограммированную на поиск нарушений определенного типа. Конечный продукт будет состоять из автоматически созданного синтаксического анализатора, который передает неутвержденные, но структурированные / идентифицированные почтовые индексы в специальную функцию проверки. Затем вы можете реорганизовать или оптимизировать.

(Вы также можете использовать грамматику для обеспечения или запрещения определенных литералов и комбинаций. Что бы ни было более читаемым или понятным для вас. Различные люди тяготеют к разным концам этих вещей.)

Вот страница, в которой подчеркиваются преимущества GOLD Parsing System. Вы можете использовать любой, который вам нравится: я просто продвигаю этот б / н, он хорошо справляется со своей работой и неуклонно улучшается на протяжении многих лет. http://www.goldparser.org/about/why-use-gold.htm

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

Если вам нужны абсолютные данные, подумайте об использовании набора данных OpenData Ordnance Survey OpenData « Code-Point® Open» , который представляет собой CSV большого количества точек данных в Великобритании (так что не в Северной Ирландии, я предполагаю), один из которых является почтовым индексом. Имейте в виду, что файл составляет 20 МБ, поэтому вам, возможно, придется преобразовать его в более управляемый формат.

Regexes трудно отлаживать, трудно переносить от одного цвета регулярного выражения к другому (молчащие «ошибки») и трудно обновлять.

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

Создание хорошо прокомментированного метода из 20 строк с простыми регулярными выражениями легко отлаживается (одно простое регулярное выражение для каждой строки), а также легко обновляется. Проблема с портированием одинакова, но, с другой стороны, вам не нужно использовать какую-то причудливую грамматическую библиотеку.

Существуют ли сторонние сервисы?

http://www.postcodeanywhere.co.uk/address-validation/

База данных GeoNames:

http://www.geonames.org/postal-codes/

+1 для комментариев «зачем». Мне пришлось использовать «официальное» регулярное выражение в различных проектах, и, хотя я никогда не пытался его сломать, он работает, и он выполняет эту работу. Я использовал его с Java и PHP-кодом без необходимости конвертировать его между форматами регулярных выражений.

Есть ли причина, по которой вам придется отлаживать ее или ломать ее?

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

Изменить: что касается обсуждения пространства / без пробела, почтовый индекс должен быть действительным с пространством или без него. Поскольку последняя часть почтового индекса (после пробела) ВСЕГДА состоит из трех цифр, можно вставить пространство вручную, что позволит вам запустить его через правило регулярных выражений.

Возьмите список допустимых почтовых индексов и проверьте, не введен ли он.