仅限英格兰邮政编码的正则表达式

时间:2012-03-07 20:00:57

标签: regex postal-code

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

应该可以通过仅使用第一个segmant(称为Postcode Area)中的字母来查看邮政编码是否为英文。总共有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(N.Ireland)

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

任何人都可以帮我创建一个只有在给定的邮政编码是英文的情况下才能匹配的正则表达式吗?

编辑 - 解决方案

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

6 个答案:

答案 0 :(得分:8)

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

但是我已经深入研究了这个问题,并且...... 可能,但这是很多工作。

要验证仅限英格兰的邮政编码,您需要排除非英文邮政编码。容易的是:

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

(我不打算提及英国以外地区的英国式邮政编码,如圣赫勒拿,直布罗陀等。从技术上讲,马恩岛和海峡群岛也不是英国的一部分,但他们'更接近英国的皇家邮政系统,并且更紧密地联系在一起。)

纯苏格兰邮政编码区域(正如您所提到的):

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

DG TD 名义上是苏格兰人,在苏格兰大部分时间都是苏格兰人。然而,一些地区延伸到苏格兰 - 英格兰边境,如下:

  • 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 2 TD15 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]

英格兰邮政编码区域 CA NE 位于英格兰 - 苏格兰边境的另一边,但它们从未延伸到苏格兰。

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

英格兰 - 威尔士边境也很复杂,但我会把这作为读者的练习。

答案 1 :(得分:4)

  

英国有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]/
    • 来自海峡群岛的不是北爱尔兰人,马克斯,......
      • 等等 ...
    • 或者您可以检查邮政编码区域是否属于大约一百个英文版,具体取决于您希望如何优化☻
  3. 请注意,语法会因您的编程语言而异。 在一个正则表达式中完成所有这些操作很快就会变得无法管理。

答案 2 :(得分:3)

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

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

在邮编地区一级仍存在问题,例如TD12在英格兰占一半,在苏格兰占一半。

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

答案 3 :(得分: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个字母或数字。希望有所帮助。

答案 4 :(得分:1)

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

标准英国邮政编码:

/^([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 PostCodes:

/^(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;

}

希望这有帮助

答案 5 :(得分: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'