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. Копировать / вставить
Как и 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 - Границы
^([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 - неправильный набор символов
^([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. Неправильный дополнительный набор символов
^([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 - Пробелы
Само 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 не по отдельным частям):
^([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 реализуется по-разному.
^([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 это):
^([A-Z][A-HJ-Y]?\d[A-Z\d]? ?\d[A-Z]{2}|GIR ?0A{2})$
2. Упрощенные шаблоны
Без указания конкретных regular-expressions буквенных символов можно postal-code использовать следующее (имейте validation в виду упрощения из 1. Исправление регулярного выражения правительства Великобритании):
^([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. Исправление регулярного выражения правительства Великобритании:
^(([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. Упрощенные шаблоны:
^(([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 так:
^((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 цифры:
^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
RegEx для сопоставления почтовых индексов Великобритании
Мы используем файлы cookies для улучшения работы сайта. Оставаясь на нашем сайте, вы соглашаетесь с условиями использования файлов cookies. Чтобы ознакомиться с нашими Положениями о конфиденциальности и об использовании файлов cookie, нажмите здесь.