【问题标题】:Regular Expression for England only Postcode正则表达式仅适用于英格兰邮政编码
【发布时间】:2012-03-07 20:00:57
【问题描述】:

我有一个 Asp.Net 网站,我想使用 RegularExpressionValidator 来检查英国邮政编码是否为英语(即它不是苏格兰、威尔士或 N.Irish)。

应该可以通过仅使用第一个段(称为邮政编码区)中的字母来查看邮政编码是否为英文。总共有 124 个邮政编码区,this 是它们的列表。

从该列表中,以下邮政编码区域不在英格兰。

  • ZE,KW,IV,HS,PH,AB,DD,PA,FK,G,KY,KA,DG,TD,EH,ML(苏格兰)
  • LL、SY、LD、HR、NP、CF、SA(威尔士)
  • BT(北爱尔兰)

正则表达式的输入可能是整个邮政编码,也可能只是邮政编码区域。

谁能帮我创建一个仅当给定邮政编码为英语时才匹配的正则表达式?

编辑 - 解决方案

在几位海报的帮助下,我能够创建以下正则表达式,我已经成功地针对 1500 多个测试用例进行了测试。

^(AL|B|B[ABDHLNRS]|C[ABHMORTVW]|D[AEHLNTY]|E|E[CNX]|FY|G[LUY]|H[ADGPUX]|I[GM‌​P]‌​​​ |JE|KT|L|L[AENSU]|M|ME|N|N[EGNRW]|O[LX]|P[ELOR]|R[GHM]|S|S[EGKLMNOPRSTW]|T[AFNQ‌​‌​​​ RSW]|UB|W|W[ACDFNRSV]|YO)\d{1,2}\s?(\d[\w]{2})?

【问题讨论】:

  • 苏格兰、威尔士和北爱尔兰有多少个代码?因为根据数字,匹配负数可能比正数更容易。
  • @Hersha 是的,我正计划做负面的事情
  • MK,您的正则表达式 en.wikipedia.org/wiki/… 中缺少米尔顿凯恩斯。供其他人参考 “GY”代表根西岛,“JE”代表泽西岛,“IM”代表马恩岛包含在正则表达式中。这可能很好,但如果你只是英国大陆,你将不得不删除这些皇冠依赖项。

标签: regex postal-code


【解决方案1】:

我已经回答过一次,指出不可能提出 100% 正确的仅限英格兰的正则表达式(因为邮政编码区域不位于政治边界内)。

不过,我已经对此进行了更深入的研究,而且……嗯,这可能的,但工作量很大。

要验证仅限英格兰的邮政编码,您需要排除非英语邮政编码。最简单的是:

  • BT(北爱尔兰)
  • IM(马恩岛)
  • JE(泽西岛)
  • GG(根西岛)
  • BF(英军)
  • BX(非地理英国邮政编码)
  • GIR(Girobank,也是非地域性的)

(我不会提及英国以外地区的英式邮政编码,例如圣赫勒拿岛、直布罗陀等。从技术上讲,马恩岛和海峡群岛也不属于英国,但它们”离英国皇家邮政系统更近,也更紧密地联系在一起。)

纯苏格兰邮政编码区域是(如您所述):

ZE,KW,IV,HS,PH,AB,DD,PA,FK,G,KY,KA,EH,ML

DGTD 名义上是苏格兰人,大部分在苏格兰。然而,一些地区延伸到苏格兰-英格兰边界,如下所示:

  • DG16 - 英格兰的一小部分
  • TD9 - 英格兰的一小部分
  • TD12 - 一半在英格兰
  • TD15 - 主要在英格兰

细分如下:

DG16 位于苏格兰,但以下英文邮政编码除外:

  • DG16 5H[TUZ]
  • DG16 5J[AB]

TD9 在苏格兰,除了 TD9 0T[JPRSTUW]

TD12只有一个扇区(TD12 4),大约一半分布在英格兰和苏格兰:

  • TD12 4[ABDEHJLN]在苏格兰
  • TD12 4[QRSTUWX]在英格兰

TD15 是最复杂的。共有 3 个扇区,其中 TD15 2TD15 9 完全在英格兰。

TD15 1分布在英格兰和苏格兰。

以下开头的邮政编码位于苏格兰:

  • TD15 1T
  • TD15 1X

...除了这些英文邮政编码:

  • TD15 1T[ABQUX]
  • TD15 1XX

TD15 1 中的所有其他邮政编码都在英格兰,以下开头的邮政编码除外:

  • TD15 1B
  • TD15 1S(即TD15 1S[ABEJLNPWXY]
  • TD15 1U(即TD15 1U[BDENPQRTUXY]

...都在英格兰,但以下邮政编码在苏格兰除外:

  • TD15 1BT
  • TD15 1S[UZ]
  • TD15 1U[FGHJLSZ]

英国邮政编码区 CANE 位于英格兰-苏格兰边界的另一侧,但它们从未延伸到苏格兰。

事实上,英国邮政编码的最后两个字母是基于邮递员实际投递邮件的方式(据我所知),因此不会理所当然地认为它会落在政治边界内。因此,如果有一组跨越边界的房屋,那么整个邮政编码(即最细粒度的级别)可能并不完全位于英格兰或苏格兰境内。例如。 TD9 0TJTD15 1UZ 非常靠近边界,我不确定它们是否完全在一侧。

英格兰和威尔士的边界也很复杂,但是我将把它留给读者作为练习。

【讨论】:

  • 嗨,吉姆。将近 4 年过去了,我发现这真的很有用。非常感谢您在这里的时间和精力。快速提问 - 这部分是否有错字:TD12 4[ABDEHJLN] are in Scotland | TD12 4[QRSTUWX] are in England?
【解决方案2】:

英国有 124 个邮政编码区。

-- PAF® statistics August 2012, 通过 List of postcodes in the United Kingdom (Wikipedia).

我建议将您的问题分成两部分(想想函数):

  1. 邮政编码有效吗?

    UK Postcode Regex (Comprehensive)

  2. 邮政编码是英文吗?

    这可以进一步细分:

    • 不是苏格兰人:
      • ! /^(ZE|KW|IV|HS|PH|AB|DD|PA|FK|G|KY|KA|DG|TD|EH|ML)[0-9]/
    • 不是威尔士语:
      • ! /^(LL|SY|LD|HR|NP|CF|SA)[0-9]/
    • 不是北爱尔兰,马恩岛,来自海峡群岛,...
      • 等等...
    • 或者您可以只检查邮政编码区是否在一百个左右的英文区中,具体取决于您要如何优化☻

请注意,语法会因您的编程语言而异。 在一个正则表达式中完成所有这些操作很快就会变得难以管理。

【讨论】:

  • 当我第一次看到这个时,我认为它不正确,但后来(我认为)你编辑了它并在最后添加了 [0-9],这改变了一切。这解决了从剩余输入中匹配字符的问题。关于仅使用英文邮政编码的第四点可能是要走的路(尽管我最初认为相反)。这是一个稍长的正则表达式,但它让我不必担心其他随机的地方,如直布罗陀、海峡群岛等......所以,这个的功劳是你的 :)
  • 我认为这行得通 ^(AL|B|B[ABDHLNRS]|C[ABHMORTVW]|D[AEHLNTY]|E|E[CNX]|FY|G[LUY]|H[ADGPUX ]|I[GM‌​P]|JE|KT|L|L[AENSU]|M|ME|N|N[EGNRW]|O[LX]|P[ELOR]|R[GHM]|S|S[ EGKLMNOPRSTW]|T[AFNQ‌​RSW]|UB|W|W[ACDFNRSV]|YO)\d{1,2}\s?(\d[\w]{2})?
  • 与内阁办公室的链接已断开。
  • @Neil:我已经替换了死链接。如果您发现死链接,请随时编辑答案。
【解决方案3】:

不可能提出仅限英格兰的正则表达式,因为邮政编码区域不位于政治边界,至少不在邮政编码区域或地区级别。

例如,CH1 在英格兰,CH5 在威尔士。

在邮政编码区层面仍然存在问题,例如TD12是英格兰的一半,苏格兰的一半。

您唯一可以依赖的地区是 BT(北爱尔兰)

【讨论】:

  • 您是对的,由于边界原因不可能 100% 正确,但我在问题编辑中发布的解决方案对于我的客户需求来说已经足够准确了。
【解决方案4】:

使用 ^(AB|AL|B| ... )$,其中 ... 是您填充其余有效部分的位置,用管道分隔 (|)。

编辑:这里有大量信息:http://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom

如果您要包含输入/输出代码,则类似于^(AB|AL|B| ... )([\d\w]{3})\s([\d\w]{3})$,它将获取其余代码。

编辑

^(A[BL]|B[ABDHLNRST]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[CNX]?|F[KY]|G[LUY]|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTWY]?|T[AFNQRSW]|UB|W[ACDFNRSV]?|YO|ZE)([\w\d]{1,2})\s?([\w\d]{3})$

这个正则表达式的一部分取自另一个答案。它匹配有效的邮政编码,然后是 1 到 2 个 {1,2} 字母 \w 或数字 \d,可选空格 \s?,然后是 3 个字母或数字。希望对您有所帮助。

【讨论】:

  • 是的,这是我最初的想法,但不会错误地排除在其他地方包含这些字符的有效邮政编码。例如 G 是 Glasgow,但有有效的英文邮政编码包含字母 G - 例如 GL
  • 这就是 ^ 和 $ 的用途 - 它强制它匹配整个字符串,而不仅仅是一部分。
  • 我试图翻转这个并输入有效的英文邮政编码。我删除了 ^ 因为我希望它与它们匹配,并尝试了几个样本。看起来像这样“(AL | B | BA | ...其余有效代码)$”它似乎不起作用。例如 HG2 8EH 不匹配,但它应该 - 我是否误解了如何做到这一点?
  • 我真的很喜欢这个解决方案,因为它验证了邮政编码结构的正确性以及它的英文性。唯一的问题(对我来说)是它需要输入整个邮政编码(并且不只处理邮政编码区域输入)。我很感激它可能对其他需要完整邮政编码验证的人有用,所以我投了赞成票。
  • 我在接受的答案中发表了评论,显示了我如何更改您的建议,使其适用于部分和完整的邮政编码以及白名单而不是黑名单
【解决方案5】:

这些是我整理的 RegEx,它们遵循英国皇家邮政为所有英国邮政编码类型定义的标准:

标准英国邮政编码:

/^([A-PR-UWYZ](?:[0-9]{1,2}|[0-9][A-HJKMNPR-Y]|[A-HK-Y][0-9]{1,2}|[A-HK-Y][0-9][ABEHMNPRVWXY]))\s*([0-9][ABD-HJLNP-UW-Z]{2})$/i

GiroBank 邮政编码:

/^(GIR)\s*(0AA)$/i

英国海外领土:

/^([A-Z]{4})\s*(1ZZ)$/i

英军邮局:

/^(BFPO)\s*(?:(c\/o)\s*)?((?(2)[0-9]{1,3}|[0-9]{1,4}))$/i

这是我编写的函数,它针对这四种类型验证邮政编码并允许类型检测:

public function UKPostCode(&$strPostCode, &$strError = null, &$strType = null, $ReturnFormatted = true) {
    $strStrippedPostCode = preg_replace("/[\s\-]/i", "", $strPostCode);

    if (empty($strStrippedPostCode)) {
        $strError = $this->__getErrorMessage("Post", "EMPTY_POST");
        return false;

    }

    $arrRegExp = array(
        "STD" => "/^([A-PR-UWYZ](?:[0-9]{1,2}|[0-9][A-HJKMNPR-Y]|[A-HK-Y][0-9]{1,2}|[A-HK-Y][0-9][ABEHMNPRVWXY]))\s*([0-9][ABD-HJLNP-UW-Z]{2})$/i",
        "GIR" => "/^(GIR)\s*(0AA)$/i",
        "OST" => "/^([A-Z]{4})\s*(1ZZ)$/i",
        "BFPO" => "/^(BFPO)\s*(?:(c\/o)\s*)?((?(2)[0-9]{1,3}|[0-9]{1,4}))$/i"
    );

    foreach ($arrRegExp as $strPostCodeType => $strExpression) {

        if (preg_match($strExpression, $strPostCode, $arrMatches)) {

            if ($ReturnFormatted !== null) {
                array_shift($arrMatches);
                $strPostCode = implode(" ", array_filter($arrMatches));
                $strPostCode = ((bool)$ReturnFormatted === true) ? strtoupper($strPostCode) : strtolower($strPostCode);

            }

            $strType = $strPostCodeType;
            return true;

        }

    }

    $strError = $this->__getErrorMessage("Post", "INVALID_POST");
    return false;

}

希望对你有帮助

【讨论】:

  • 这里没有任何内容可以回答有关英格兰仅邮政编码的实际问题,但作为一种资源很有用,因此感谢您的贡献。我会给你前 10 分 - 欢迎来到 SO :)
【解决方案6】:
'A[BL]|B[ABDHLNRST]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[CNX]?|F[KY]|G[LUY]|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTWY]?|T[AFNQRSW]|UB|W[ACDFNRSV]?|YO|ZE'

【讨论】:

  • 我已经尝试过这个正则表达式,它返回了许多非英语邮政编码的匹配项......例如 G11 5EH(格拉斯哥 - 它在“E”上匹配)。任何在 incode 中包含任何单字母 outcode 的内容都与此正则表达式匹配......这是我在 Derreck Dean 的回答中提到的相同问题
猜你喜欢
  • 2013-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多