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

Я недавно разместил an answer в this question on UK postcodes for the R language. Я regex обнаружил, что шаблон регулярного выражения правительства Великобритании неверен и не может regular-expression должным образом проверить некоторые почтовые regex-group индексы. К сожалению, многие validate ответы здесь основаны на postcode этом неправильном шаблоне.

Я regular-expression опишу некоторые из этих проблем input-validation ниже и предоставлю исправленное postal-code регулярное выражение, которое validation действительно работает.


Примечание

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

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

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

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

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

Это неправильное regex регулярное выражение, которое regular-expressions правительство Великобритании regex предоставило разработчикам regular-expressions (не знаю, как долго эта ссылка regular-expressions будет работать, но вы можете form-validation увидеть это в их Bulk Data Transfer documentation):

^([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. Копировать / вставить

See regex in use here.

Как и input-validation многие разработчики, они regexp копируют / вставляют код form-validation (особенно регулярные выражения) и regular-expression вставляют его, ожидая, что validation они будут работать. Хотя postcode это замечательно в теории, в regexp данном конкретном случае form-validation это не удается, потому что validate копирование / вставка из regex этого документа фактически regexp меняет один из символов (пробел) на validate символ новой строки, как validate показано ниже:

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

Первое, что validate сделает большинство разработчиков, это input-validation просто сотрет новую строку, не regular-expressions задумываясь. Теперь регулярное postal-code выражение не будет сопоставлять postcode почтовые индексы с пробелами regex-group в них (кроме почтового индекса validation GIR 0AA).

Чтобы решить эту проблему, символ regular-expressions новой строки следует заменить validate пробелом:

^([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 - Границы

See regex in use here.

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

Регулярное выражение regex почтового индекса неправильно validation привязывает регулярное выражение. Любой, кто regex-group использует это регулярное postal-code выражение для проверки почтовых postal-code индексов, может быть удивлен, если validate получит значение вроде fooA11 1AA. Это regularexpression потому, что они закрепили regularexpression начало первой опции и конец regexp второй опции (независимо regexp друг от друга), как указано regular-expression в регулярном выражении выше.

Это regexp означает, что ^ (утверждает input-validation позицию в начале строки) работает regular-expression только с первым параметром validation ([Gg][Ii][Rr] 0[Aa]{2}), поэтому второй вариант validation проверяет любые строки, которые postal-code заканчиваются в почтовом индексе. (независимо validation от того, что было раньше).

Точно regexp так же первая опция не привязана postal-code к концу строки $, поэтому regex 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})$

Чтобы regular-expression решить эту проблему, оба regular-expressions параметра должны быть заключены regularexpression в другую группу (или группу validate без захвата), а вокруг нее validation должны быть размещены якоря:

^(([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 - неправильный набор символов

See regex in use here.

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

В regular-expression регулярном выражении отсутствует regular-expressions -, указывающий на диапазон regex-group символов. В его нынешнем validation виде, если почтовый индекс input-validation имеет формат ANA NAA (где A представляет validate букву, а N представляет собой regex число), и он начинается с form-validation любого другого значения, кроме postcode A или Z, он завершится ошибкой.

Это regular-expression означает, что он будет соответствовать regular-expression A1A 1AA и Z1A 1AA, но не B1A 1AA.

Чтобы устранить regularexpression эту проблему, символ - следует validate поместить между A и Z в соответствующем validate наборе символов:

^([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. Неправильный дополнительный набор символов

See regex in use here.

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

Клянусь, они postcode даже не тестировали эту штуку, прежде regular-expressions чем опубликовать ее в Интернете. Они regularexpression сделали неправильный набор validate символов необязательным. Они regularexpression сделали опцию [0-9] в четвертом validation подварианте опции 2 (группа postal-code 9). Это позволяет регулярному validation выражению сопоставлять неправильно input-validation отформатированные почтовые regular-expressions индексы, такие как AAA 1AA.

Чтобы input-validation устранить эту проблему, вместо regex этого сделайте следующий input-validation класс символов необязательным form-validation (и впоследствии сделайте regularexpression так, чтобы набор [0-9] соответствовал regularexpression ровно один раз):

^([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 - Производительность

Производительность form-validation этого регулярного выражения validation очень низкая. Во-первых, они validation поместили наименее вероятный regular-expressions вариант шаблона для соответствия validate GIR 0AA в начале. Сколько пользователей, вероятно, будет regex иметь этот почтовый индекс postal-code по сравнению с любым другим input-validation почтовым индексом; наверное postal-code никогда? Это означает, что form-validation каждый раз, когда используется postcode регулярное выражение, оно validate должно сначала исчерпать input-validation эту опцию, прежде чем переходить postcode к следующей опции. Чтобы regular-expressions увидеть, как это сказывается postal-code на производительности, сравните regexp количество шагов, сделанных regular-expression original regex (35) с same regex after having flipped the options (22).

Вторая проблема postcode с производительностью связана regularexpression со структурой всего регулярного regexp выражения. Нет смысла возвращаться validation к каждому варианту, если regex-group один из них терпит неудачу. Структурирование regex текущего регулярного выражения validate можно значительно упростить. Я regular-expressions исправляю это в разделе Ответ.

Проблема 6 - Пробелы

See regex in use here

Само regular-expression по себе это не может считаться validate проблемой, но вызывает беспокойство validation у большинства разработчиков. Пробелы regular-expression в регулярном выражении не postcode являются обязательными, это regexp означает, что пользователи, вводящие regex-group свои почтовые индексы, должны regular-expressions помещать пробелы в почтовых postcode индексах. Это легко исправить, просто validate добавив ? после пробелов, чтобы postcode сделать их необязательными. См. Исправление regular-expressions в разделе Ответ.


Ответ

1. Исправление регулярного выражения правительства Великобритании

Устранение всех regularexpression проблем, описанных в разделе regularexpression Проблемы, и упрощение шаблона дает regexp следующий, более короткий regular-expression и сжатый шаблон. Мы также validate можем удалить большинство regex групп, поскольку мы проверяем input-validation почтовый индекс в целом (а regular-expressions не по отдельным частям):

See regex in use here

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

Это validation можно дополнительно сократить, удалив regex-group все диапазоны из одного из postcode регистров (верхний или нижний regularexpression регистр) и используя флаг postal-code без учета регистра. Примечание. На regexp некоторых языках его нет, поэтому regex-group используйте более длинный, указанный validate выше. В каждом языке флаг regexp нечувствительности к регистру postal-code реализуется по-разному.

See regex in use here.

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

Короче, снова regular-expression заменив [0-9] на \d (если ваш механизм postcode регулярных выражений поддерживает validation это):

See regex in use here.

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

2. Упрощенные шаблоны

Без указания конкретных regular-expressions буквенных символов можно postal-code использовать следующее (имейте validation в виду упрощения из 1. Исправление регулярного выражения правительства Великобритании):

See regex in use here.

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

И regular-expressions даже более того, если вас postcode не волнует особый случай input-validation GIR 0AA:

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

3. Сложные узоры

Я бы не предлагал чрезмерно input-validation подтверждать почтовый индекс, поскольку postal-code новые районы, районы и субрайоны postal-code могут появиться в любой момент regular-expression времени. То, что я предлагаю regular-expression сделать потенциально, - это добавить postcode поддержку крайних случаев. Существуют regular-expression некоторые особые случаи, которые regexp описаны в this Wikipedia article.

Вот сложные регулярные regularexpression выражения, которые включают form-validation подразделы 3. (3.1, 3.2, 3.3).

Что validate касается шаблонов в 1. Исправление регулярного выражения правительства Великобритании:

See regex in use here

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

А в postal-code отношении 2. Упрощенные шаблоны:

See regex in use here

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

В статье Википедии regex в настоящее время говорится input-validation (некоторые форматы немного regular-expressions упрощены):

  • 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: Бермудские острова (согласно this document)
  • KY1-1111: Каймановы острова (согласно this document)
  • VG1111: Британские Виргинские острова (согласно this document).
  • MSR 1111: Монтсеррат (согласно this document)

Всеохватывающее validate регулярное выражение, соответствующее regexp только британским заморским input-validation территориям, может выглядеть input-validation так:

See regex in use here.

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

Хотя они недавно были postal-code изменены для лучшего соответствия postal-code британской системе почтовых regex индексов на BF# (где # представляет form-validation собой число), они считаются postal-code необязательными альтернативными почтовыми индексами. Эти почтовые индексы следуют validation (редактировать) формату BFPO, за form-validation которым следуют 1–4 цифры:

See regex in use here

^BFPO ?\d{1,4}$

3.3 Санта?

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

^SAN ?TA1$

regex

validation

regex-group

postal-code

2022-11-14T01:53:48+00:00
Вопросы с похожей тематикой, как у вопроса:

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