我正在使用正则表达式,它将仅在输入字符串中验证完整复杂的英国邮政编码。所有不常见的邮政编码表格都必须与通常一样。例如:
匹配
不匹配
如何解决这个问题?
答案 0 :(得分:177)
我建议您查看英国政府数据标准的邮政编码[现已链接死亡; archive of XML,请参阅Wikipedia进行讨论]。有关于数据的简要描述,附加的xml架构提供了正则表达式。它可能不是你想要的,但它将是一个很好的起点。 RegEx略微不同于XML,因为给定的定义允许A9A 9AA格式的第三位P字符。
英国政府提供的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开头),并且它们确实提供了一个你可以尝试的更严格的测试。
答案 1 :(得分:79)
看起来我们将要使用^(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 Schema处的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}))$
这不包括海外领土,只强制执行格式,而不是存在不同的区域。它基于以下规则:
可以接受以下格式:
其中:
祝福
科林
答案 2 :(得分:41)
没有全面的英国邮政编码正则表达式能够验证邮政编码。您可以使用正则表达式检查邮政编码是否格式正确;并不是说它确实存在。
邮政编码是任意复杂且不断变化的。例如,对于每个邮政编码区域,输出代码W1
不会,也可能永远不会有1到99之间的每个数字。
你不能指望目前永远存在的是什么。例如,1990年,邮局决定阿伯丁变得有点拥挤。他们在AB1-5的末尾添加了0,使其成为AB10-50,然后在这些之间创建了许多邮政编码。
每当构建新街道时,都会创建新的邮政编码。这是获得构建许可的过程的一部分;地方当局有义务在邮局更新(不是他们都这样做)。
此外,正如许多其他用户所指出的那样,有特殊的邮政编码,如Girobank,GIR 0AA,以及圣诞老人信件,SAN TA1 - 您可能不希望在那里发布任何内容,但它不会似乎被任何其他答案所涵盖。
然后,有BFPO邮政编码,现在是changing to a more standard format。两种格式都有效。最后,还有海外领地 source Wikipedia 。
+----------+----------------------------------------------+ | Postcode | Location | +----------+----------------------------------------------+ | AI-2640 | Anguilla | | ASCN 1ZZ | Ascension Island | | STHL 1ZZ | Saint Helena | | TDCU 1ZZ | Tristan da Cunha | | BBND 1ZZ | British Indian Ocean Territory | | BIQQ 1ZZ | British Antarctic Territory | | FIQQ 1ZZ | Falkland Islands | | GX11 1AA | Gibraltar | | PCRN 1ZZ | Pitcairn Islands | | SIQQ 1ZZ | South Georgia and the South Sandwich Islands | | TKCA 1ZZ | Turks and Caicos Islands | +----------+----------------------------------------------+
接下来,您必须考虑到英国将其邮政编码系统“导出”到世界上许多地方。验证“英国”邮政编码的任何内容也将验证许多其他国家/地区的邮政编码。
如果您想验证英国邮政编码,最安全的方法是使用当前邮政编码的查找。有很多选择:
Ordnance Survey根据开放数据许可证发布Code-Point Open。它将落后于时代,但它是免费的。这将(可能 - 我不记得)不包括北爱尔兰的数据,因为军械测量局没有在那里进行调查。北爱尔兰的地图由北爱尔兰军械测量局进行,他们有单独的付费Pointer产品。您可以使用它并附加少量未被轻易覆盖的内容。
皇家邮政发布Postcode Address File (PAF),其中包括我不确定Code-Point Open的BFPO。它定期更新,但需要花钱(有时它们可能是彻头彻尾的意思)。 PAF包含完整地址而不仅仅是邮政编码,并附带自己的Programmers Guide。开放数据用户组(ODUG)目前正在游说让PAF免费发布,here's a description of their position。
最后,有AddressBase。这是Ordnance Survey,地方当局,皇家邮政和匹配公司之间的合作,以创建关于所有英国地址的所有信息的权威目录(它们也相当成功)。这是付费的,但如果您与地方当局,政府部门或政府服务部门合作,他们可以免费使用。除了包含的邮政编码之外,还有更多的信息。
答案 3 :(得分:26)
我最近将an answer发布到this question on UK postcodes for the R language。我发现英国政府的正则表达式模式不正确,并且无法正确验证某些邮政编码。不幸的是,这里的许多答案都是基于这种不正确的模式。
我将在下面概述其中的一些问题,并提供一个实际上有效的修改后的正则表达式。
我的答案(以及一般的正则表达式):
如果您不关心不良正则表达式,而只想跳到答案,请向下滚动至答案部分。
不应使用本节中的正则表达式。
这是英国政府为开发人员提供的失败的正则表达式(不确定此链接将打开多长时间,但是您可以在他们的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})$
正如许多开发人员可能做的那样,他们复制/粘贴代码(尤其是正则表达式)并粘贴它们,以期望它们能正常工作。虽然从理论上讲这很好,但是在这种特殊情况下失败了,因为从此文档中进行复制/粘贴实际上会将一个字符(空格)更改为换行符,如下所示:
^([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})$
^
^([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
之类的值,则使用此正则表达式验证邮政编码的任何人都可能会感到惊讶。正如上面的regex所指出的那样,这是因为它们锚定了第一个选项的开始和第二个选项的结束(彼此独立)。
这意味着^
(在行首处的断言位置)仅适用于第一个选项([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}))$
^^ ^^
^([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})$
^
^([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(第9组)的第四个子选项中设置了[0-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})$
^
此正则表达式的性能非常差。首先,他们在开头放置了最不可能匹配GIR 0AA
的模式选项。与其他邮政编码相比,有多少用户将可能拥有此邮政编码;可能永远不会?这意味着每次使用正则表达式时,必须先用尽此选项,然后才能继续使用下一个选项。要查看性能如何受到影响,请检查original regex相对于same regex after having flipped the options(22)采取的步骤(35)。
性能的第二个问题是由于整个正则表达式的结构方式。如果每个选项失败,则没有回溯的意义。当前正则表达式的结构方式可以大大简化。我在答案部分中为此提供了解决方法。
从本质上讲,这也许不算是一个问题,但确实引起了大多数开发人员的关注。正则表达式中的空格不是可选的,这意味着输入邮政编码的用户必须在邮政编码中放置一个空格。通过简单地在空格后添加?
使其变为可选,可以轻松解决此问题。请参见答案部分以获取修复。
解决问题部分中概述的所有问题并简化模式将产生以下更简短,更简洁的模式。我们也可以删除大多数组,因为我们要验证整个邮政编码(而不是单个部分):
^([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})$
(如果您的正则表达式引擎支持):
^([A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}|GIR ?0A{2})$
在不确保特定字母字符的情况下,可以使用以下命令(请记住, 1。简化了英国政府的Regex 的用法)
GIR 0AA
更进一步,如果您不在乎特殊情况^[A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}$
:
^(([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)$
我不建议对邮政编码进行过度验证,因为新的地区,地区和分区可能会随时出现。我将建议可能做的是增加了对边缘情况的支持。存在一些特殊情况,并在this Wikipedia article中进行了概述。
这是复杂的正则表达式,其中包括 3。(3.1、3.2、3.3)小节。
关于 1中的模式。修复英国政府的正则表达式:
^(([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)$
与 2有关。简化模式:
AI-1111
Wikipedia文章当前指出(某些格式略有简化):
ASCN 1ZZ
:安圭拉STHL 1ZZ
:上生之岛TDCU 1ZZ
:圣赫勒拿岛BBND 1ZZ
:特里斯坦·达·库尼亚(Tristan da Cunha)BIQQ 1ZZ
:英属印度洋领地FIQQ 1ZZ
:不列颠南极领地GX11 1ZZ
:福克兰群岛PCRN 1ZZ
:直布罗陀SIQQ 1ZZ
:皮特凯恩群岛TKCA 1ZZ
:南乔治亚岛和南桑威奇群岛BFPO 11
:特克斯和凯科斯群岛ZZ 11
:Akrotiri和Dhekelia GE CX
和KY1-1111
:百慕大(根据this document)VG1111
:开曼群岛(根据this document)MSR 1111
:英属维尔京群岛(根据this document)^((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)$
:蒙特塞拉特(根据this document)仅与英国海外领土匹配的功能全面的正则表达式可能如下所示:
BF#
尽管最近对其进行了更改,以便更好地与英国邮政编码系统保持一致,以#
(其中BFPO
代表数字),但它们被视为可选的替代邮政编码。这些邮政编码遵循^BFPO ?\d{1,4}$
的格式,后接1-4位数字:
SAN TA1
圣诞老人还有另一种特殊情况(如其他答案所述):^SAN ?TA1$
是有效的邮政编码。正则表达式非常简单:
{{1}}
答案 4 :(得分:20)
我查看了上面的一些答案,我建议不要使用来自@ Dan answer (c. Dec 15 '10)的模式,因为它错误地将几乎0.4%的有效邮政编码标记为无效,而其他人则没有。
Ordnance Survey提供名为Code Point Open的服务:
包含英国所有当前邮政编码单元的列表
我使用grep
从这些数据中对照完整的邮政编码列表(2013年7月6日)运行上面的每个正则表达式:
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
我没有说过哪种模式最适合过滤掉无效的邮政编码。
答案 5 :(得分:17)
^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$
正则表达式匹配有效的UK 邮政编码。在英国的邮政系统没有 所有字母都用于所有位置 (与车辆登记相同 (并且有各种规则) 治理这个。这个正则表达式考虑到了 考虑这些规则。细节 规则:邮政编码的前半部分有效 格式[A-Z] [A-Z] [0-9] [A-Z] [A-Z] [A-Z] [0-9] [0-9] [A-Z] [0-9] [0-9] [A-Z] [A-Z] [0-9] [A-Z] [A-Z] [A-Z] [A-Z] [0-9] [A-Z] [A-Z] [0-9]例外 位置 - 第一。约束 - QVX没有 使用位置 - 第二。约束 - IJZ除GIR 0AA外没有使用过 立场 - 第三。约束 - AEHMNPRTVXY仅使用位置 - 向前。约束 - ABEHMNPRVWXY第二 邮政编码的一半有效格式 [0-9] [A-Z] [A-Z]例外位置 - 第二和第三。约束 - CIKMOV 没用过
答案 6 :(得分: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})|(([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})$
更新:Jamie Bull指出的更新的正则表达式。不确定这是我的错误复制还是政府正则表达式中的错误,链接现在已经关闭......
更新:正如ctwheels发现的,这个正则表达式适用于javascript正则表达式。请参阅他对pcre(php)风格的评论。
答案 7 :(得分:12)
根据这个维基百科表
此模式涵盖所有案例
freeze: true
在Android \ Java上使用时,请使用\\ d
答案 8 :(得分:12)
一个旧帖子,但谷歌搜索结果仍然相当高,所以我认为我会更新。 10月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})$
从:
该文件还解释了其背后的逻辑。但是,它有一个错误(粗体)并且还允许小写,虽然合法不通常,所以修改版本:
^(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)。
答案 9 :(得分: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 :(得分: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
对我而言,这是在尽可能多的验证之间取得适当的平衡,同时确保面向未来并且易于维护。
答案 11 :(得分:9)
我在最后一天左右一直在寻找英国邮政编码正则表达式,并偶然发现了这个帖子。我按照上面的大部分建议进行了工作,但没有一个对我有用,所以我提出了自己的正则表达式,据我所知,截至2013年1月,所有有效的英国邮政编码都是根据皇家邮报)。
正则表达式和一些简单的邮政编码检查PHP代码发布如下。注意: - 它允许使用较低或大写的邮政编码和GIR 0AA异常,但是为了处理输入的邮政编码中间的空间,很可能还会使用简单的str_replace来删除测试前的空间反对正则表达式。除此之外的任何差异和皇家邮政本身甚至都没有在他们的文献中提及它们(见http://www.royalmail.com/sites/default/files/docs/pdf/programmers_guide_edition_7_v5.pdf并从第17页开始阅读)!
注意:在皇家邮政自己的文献(上面的链接)中,如果这些字符是字母,则第3和第4个位置存在轻微的歧义,并且存在例外情况。我直接联系了皇家邮政,并用他们自己的话说明了“Award NAA格式的外向代码第4位的信件没有例外,第3个位置例外仅适用于”外展代码“的最后一个字母。格式ANA NAA。“直接从马的嘴里出来!
<?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>";
}
?>
我希望它可以帮助遇到此线程的其他任何人寻找解决方案。
答案 12 :(得分: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}$/
答案 13 :(得分: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})$
似乎更准确一点,请参阅Wikipedia article entitled 'Postcodes in the United Kingdom'。
请注意,此正则表达式只需要大写字符。
更大的问题是,您是否限制用户输入以仅允许实际存在的邮政编码,或者您是否只是试图阻止用户在表单字段中输入完整的垃圾。正确匹配每个可能的邮政编码,以及将来证明它,是一个更难的难题,除非你是HMRC,否则可能不值得。
答案 14 :(得分: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})
它假定邮政编码已转换为大写但没有前导或尾随字符,但会在outcode和incode之间接受可选空格。
特殊&#34; GIR0 0AA&#34;邮政编码被排除在外并且不会验证,因为它不在邮政编码的官方邮局列表中,并且据我所知,不会被用作注册地址。如果需要,添加它应该是一个特殊情况。
答案 15 :(得分: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)$
针对我们的客户数据库进行测试,看起来非常准确。
答案 16 :(得分: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*$)
答案 17 :(得分:3)
我想要一个简单的正则表达式,允许太多,但不要拒绝有效的邮政编码。我选择了这个(输入是一个剥离/修剪过的字符串):
/^([a-z0-9]\s*){5,7}$/i
长度5到7(不包括空白)意味着我们允许使用最短的邮编,如“L1 8JQ”以及最长的邮编,如“OL14 5ET”。
编辑:将8更改为7,因此我们不允许使用8个字符的邮政编码。
答案 18 :(得分:3)
这里是我们处理英国邮政编码问题的方式:
^([A-Za-z]{1,2}[0-9]{1,2}[A-Za-z]?[ ]?)([0-9]{1}[A-Za-z]{2})$
<强>解释强>
这得到大多数格式,然后我们使用数据库验证邮政编码是否真实,这个数据是由开放点https://www.ordnancesurvey.co.uk/opendatadownload/products.html
驱动的希望这会有所帮助
答案 19 :(得分:3)
根据皇家邮政programmer's guide检查邮政编码的有效格式:
|----------------------------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" ]
答案 20 :(得分:3)
邮政编码的前半部分有效格式
例外
位置1 - 未使用QVX
位置2 - 除了GIR 0AA外,未使用IJZ
位置3 - AEHMNPRTVXY仅使用
第4位 - ABEHMNPRVWXY
邮政编码的后半部分
例外
位置2 + 3 - 未使用CIKMOV
请记住,并非使用所有可能的代码,因此此列表对于有效代码是必要但不充分的条件。可能更容易匹配所有有效代码的列表?
答案 21 :(得分: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}))$
此正则表达式允许大写和小写字母之间有可选空格
从软件开发人员的角度来看,这个正则表达式对于地址可选的软件非常有用。例如,如果用户不想提供他们的地址详细信息
答案 22 :(得分:1)
接受的答案反映了皇家邮政的规则,尽管正则表达式中存在拼写错误。这个错字似乎也出现在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})
它还包括第一个和第二个块之间的可选空间。
答案 23 :(得分:1)
我们得到了一个规范:
UK postcodes must be in one of the following forms (with one exception, see below): § A9 9AA § A99 9AA § AA9 9AA § AA99 9AA § A9A 9AA § AA9A 9AA where A represents an alphabetic character and 9 represents a numeric character. Additional rules apply to alphabetic characters, as follows: § The character in position 1 may not be Q, V or X § The character in position 2 may not be I, J or Z § The character in position 3 may not be I, L, M, N, O, P, Q, R, V, X, Y or Z § The character in position 4 may not be C, D, F, G, I, J, K, L, O, Q, S, T, U or Z § The characters in the rightmost two positions may not be C, I, K, M, O or V The one exception that does not follow these general rules is the postcode "GIR 0AA", which is a special valid postcode.
我们想出了这个:
/^([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
但请注意 - 这允许组之间的任意数量的空格。
答案 24 :(得分: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 --------------------&gt; ONLY POSTER POSTCODE
A1 1AA ------------------&gt;(外部和内部)POSTCODE的组合
WC2A --------------------&GT; OUTER
答案 25 :(得分:1)
我在几乎所有变体和大规模转移的正则表达式中找到了什么,以及维基百科网站上的内容是什么,特别是对于维基百科正则表达式,在第一个之后需要有一个^(垂直条) 。我通过测试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})$
答案 26 :(得分:1)
查看此页面上的python代码:
http://www.brunningonline.net/simon/blog/archives/001292.html
我有一些邮政编码解析要做。要求非常简单;我必须将邮政编码解析为outcode和(可选)incode。好消息是我不需要进行任何验证 - 我只需要以模糊的方式切断我提供的内容。在格式化方面,我无法假设我的导入,即大小写和嵌入空格。但这不是坏消息;坏消息是我必须在RPG中全部完成。 : - (
然而,我把一些Python函数放在一起以澄清我的想法。
我用它来为我处理邮政编码。
答案 27 :(得分:1)
通过经验测试和观察以及用https://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom#Validation进行确认,这是我的Python regex版本,可以正确解析和验证英国邮政编码:
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)
答案 28 :(得分: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;
答案 29 :(得分: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!"}
答案 30 :(得分:0)
我从XML文档中窃取了它,而且似乎涵盖了没有硬编码GIRO的所有情况:
%r{[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9][A-Z]{2}}i
(带有忽略大小写的Ruby语法)