我在一个正则表达式后,将验证一个完整的复杂的英国邮政编码只在输入字符串。所有不常见的邮政编码形式必须包括以及通常。例如:
匹配
CW3 9不锈钢 SE5 0EG SE50EG Se5 0eg WC2H 7LT
不匹配
aWC2H 7LT WC2H 7LTa WC2H
我怎么解决这个问题?
我在一个正则表达式后,将验证一个完整的复杂的英国邮政编码只在输入字符串。所有不常见的邮政编码形式必须包括以及通常。例如:
匹配
CW3 9不锈钢 SE5 0EG SE50EG Se5 0eg WC2H 7LT
不匹配
aWC2H 7LT WC2H 7LTa WC2H
我怎么解决这个问题?
当前回答
我从一个XML文档中窃取了这个,它似乎涵盖了没有硬编码的GIRO的所有情况:
%r{[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9][A-Z]{2}}i
(Ruby语法忽略大小写)
其他回答
我发现在几乎所有的变化和regex从批量转移pdf和什么是在维基百科网站上是这样的,特别是维基百科的regex是,需要有一个^后的第一个|(竖条)。我通过测试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})$
我看了一下上面的一些答案,我不建议使用@Dan的答案(12月15日至10日)中的模式,因为它错误地将近0.4%的有效邮政编码标记为无效,而其他的则没有。
军械测量所提供的代号开放服务包括:
包含英国所有当前邮政编码单位的列表
我使用grep从这些数据中针对完整的邮政编码列表(7月6日至13日)运行了上面的每个正则表达式:
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个。
以下是与每个$模式不匹配的有效邮政编码的数量:
'^([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
在过滤无效邮编方面,我并没有说哪种模式是最好的。
邮政编码可能会发生变化,验证邮政编码的唯一真正方法是拥有完整的邮政编码列表,并查看它是否存在。
但是正则表达式很有用,因为它们:
是否易于使用和实现 是短暂的 都跑得很快 相当容易维护(与完整的邮政编码列表相比) 仍然捕获大多数输入错误
但是正则表达式往往很难维护,特别是对于那些一开始就没有想到它的人来说。所以它一定是:
尽量简单易懂 相对未来的证明
这意味着这个答案中的大多数正则表达式都不够好。例如,我可以看到[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
对我来说,这是尽可能多地验证之间的正确平衡,与此同时,未来的验证和易于维护。
这是谷歌在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}
看看本页的python代码:
http://www.brunningonline.net/simon/blog/archives/001292.html
I've got some postcode parsing to do. The requirement is pretty simple; I have to parse a postcode into an outcode and (optional) incode. The good new is that I don't have to perform any validation - I just have to chop up what I've been provided with in a vaguely intelligent manner. I can't assume much about my import in terms of formatting, i.e. case and embedded spaces. But this isn't the bad news; the bad news is that I have to do it all in RPG. :-( Nevertheless, I threw a little Python function together to clarify my thinking.
我用它来处理邮政编码。