5

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

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

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

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

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

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

编辑 - 解决方案

在几张海报的帮助下,我能够创建以下正则表达式,我已经成功地针对 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})?

4

6 回答 6

10

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

但是,我对此进行了更深入的研究,并且……这可能的,但是要做很多工作。

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

  • 英国电信(北爱尔兰)
  • 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[乌兹别克斯坦]
  • TD15 1U[FGHJLSZ]

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

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

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

于 2013-08-02T23:36:10.447 回答
4

英国有 124 个邮政编码区。

- PAF® 统计 2012 年 8 月来自 英国邮政编码列表(维基百科)

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

  1. 邮编有效吗?

    英国邮政编码正则表达式(综合)

  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]/
    • 不是来自海峡群岛的北爱尔兰,马恩岛,......
      • 等等……
    • 或者您可以只检查邮政编码区是否在一百个左右的英文区中,具体取决于您要如何优化☻

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

于 2012-03-07T20:25:23.023 回答
3

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

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

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

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

于 2012-11-30T00:04:21.783 回答
1

使用^(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 个字母或数字。希望有帮助。

于 2012-03-07T20:09:58.323 回答
1

这些是我整理的 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;

}

希望这可以帮助

于 2013-07-17T18:25:52.413 回答
0
'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'
于 2012-03-07T20:18:56.607 回答