我在一个正则表达式后,将验证一个完整的复杂的英国邮政编码只在输入字符串。所有不常见的邮政编码形式必须包括以及通常。例如:

匹配

CW3 9不锈钢 SE5 0EG SE50EG Se5 0eg WC2H 7LT

不匹配

aWC2H 7LT WC2H 7LTa WC2H

我怎么解决这个问题?


当前回答

通过经验测试和观察,以及https://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom#Validation的确认,以下是我的Python正则表达式版本,可以正确地解析和验证英国邮政编码:

UK_POSTCODE_REGEX = r ' (? P < postcode_area > [a - z] {1,2}) (? P <区> (?:[0 - 9]{1,2})| (?:[0 - 9][a - z])) (? P <部门> [0 - 9])(? P <邮编> [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)

其他回答

我需要一个可以在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;

我建议你看看英国政府的邮政编码数据标准[链接现在死了;XML的存档,参见维基百科的讨论]。这里有关于数据的简要描述,附带的xml模式提供了一个正则表达式。这可能不是你想要的,但会是一个很好的起点。RegEx与XML略有不同,因为给定的定义允许在格式A9A 9AA中第三个位置的P字符。

英国政府提供的正则表达式为:

([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开头的邮政编码),并且它们确实提供了一个更严格的测试,您可以尝试一下。

不存在能够验证邮政编码的综合英国邮政编码正则表达式。您可以使用正则表达式检查邮政编码的格式是否正确;并不是真的存在。

邮政编码非常复杂,而且不断变化。例如,对于每个邮政编码区域,出码W1没有,也可能永远没有1到99之间的每个数字。

你不能指望当前的东西永远都是真的。举个例子,1990年,邮局认为阿伯丁有点拥挤了。他们在AB1-5的末尾加了一个0,使它成为AB10-50,然后在这些之间创建了一些邮政编码。

每当建立一条新街道时,就会创建一个新的邮政编码。这是获得建筑许可的过程的一部分;地方当局有义务与邮局保持更新(并不是说他们都这样做)。

此外,正如许多其他用户指出的那样,还有一些特殊的邮政编码,如Girobank, GIR 0AA,以及给圣诞老人的信件,SAN TA1 -你可能不想在那里张贴任何东西,但似乎没有任何其他答案。

然后,还有BFPO的邮政编码,现在正在改为更标准的格式。两种格式都是有效的。最后,还有海外领土来源维基百科。

+----------+----------------------------------------------+
| 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 releases Code-Point Open under an open data licence. It'll be very slightly behind the times but it's free. This will (probably - I can't remember) not include Northern Irish data as the Ordnance Survey has no remit there. Mapping in Northern Ireland is conducted by the Ordnance Survey of Northern Ireland and they have their, separate, paid-for, Pointer product. You could use this and append the few that aren't covered fairly easily. Royal Mail releases the Postcode Address File (PAF), this includes BFPO which I'm not sure Code-Point Open does. It's updated regularly but costs money (and they can be downright mean about it sometimes). PAF includes the full address rather than just postcodes and comes with its own Programmers Guide. The Open Data User Group (ODUG) is currently lobbying to have PAF released for free, here's a description of their position. Lastly, there's AddressBase. This is a collaboration between Ordnance Survey, Local Authorities, Royal Mail and a matching company to create a definitive directory of all information about all UK addresses (they've been fairly successful as well). It's paid-for but if you're working with a Local Authority, government department, or government service it's free for them to use. There's a lot more information than just postcodes included.

我今天做了英国邮政编码验证的正则表达式,据我所知,它适用于所有的英国邮政编码,如果你放一个空格或如果你不放。

^((([a-zA-Z][0-9])|([a-zA-Z][0-9]{2})|([a-zA-Z]{2}[0-9])|([a-zA-Z]{2}[0-9]{2})|([A-Za-z][0-9][a-zA-Z])|([a-zA-Z]{2}[0-9][a-zA-Z]))(\s*[0-9][a-zA-Z]{2})$)

如果有什么格式没有涵盖,请告诉我

我有英国邮政编码验证的正则表达式。

这是适用于所有类型的邮政编码,无论是内部或外部

^((([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 -------------------->仅为外部邮政编码 A1 1 aa ------------------> (内部和外部)邮政编码的组合 WC2A --------------------> 外