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

匹配

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

不匹配

aWC2H 7LT WC2H 7LTa WC2H

我怎么解决这个问题?


当前回答

邮政编码可能会发生变化,验证邮政编码的唯一真正方法是拥有完整的邮政编码列表,并查看它是否存在。

但是正则表达式很有用,因为它们:

是否易于使用和实现 是短暂的 都跑得很快 相当容易维护(与完整的邮政编码列表相比) 仍然捕获大多数输入错误

但是正则表达式往往很难维护,特别是对于那些一开始就没有想到它的人来说。所以它一定是:

尽量简单易懂 相对未来的证明

这意味着这个答案中的大多数正则表达式都不够好。例如,我可以看到[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

对我来说,这是尽可能多地验证之间的正确平衡,与此同时,未来的验证和易于维护。

其他回答

前半段邮政编码有效格式

[a - z] [a - z][0 - 9]的[a -ž] [a - z] [a - z] [0 - 9] [0 - 9] [a - z] [0 - 9] [0 - 9] [a - z] [a - z] [0 - 9] [a - z] [a - z]的[a -ž] [a - z][0 - 9]的[a -ž] [a - z] [0 - 9]

异常 位置1 - QVX未使用 位置2 -除GIR 0AA外,IJZ不使用 位置3 - AEHMNPRTVXY只使用 位置4 - ABEHMNPRVWXY

邮政编码的后半部分

[0 - 9] [a - z]的[a -ž]

异常 位置2+3 - CIKMOV未使用

记住,不是所有可能的代码都被使用了,所以这个列表是有效代码的必要条件,而不是充分条件。只是匹配所有有效代码的列表可能会更容易?

以下是我们处理英国邮政编码问题的方法:

^([A-Za-z]{1,2}[0-9]{1,2}[A-Za-z]?[ ]?)([0-9]{1}[A-Za-z]{2})$

解释:

期望有1或2个a-z字符,上或下都没问题 预期有1到2个数字 期望0或1个a-z字符,上或下精细 允许使用可选空间 期望1个数字 期望有2个a-z,上下都没问题

这将获得大多数格式,然后我们使用db来验证邮政编码是否真实,该数据由openpoint https://www.ordnancesurvey.co.uk/opendatadownload/products.html驱动

希望这能有所帮助

我一直在寻找一个英国邮政编码正则表达式的最后一天左右,无意中发现了这个线程。我尝试了上面的大部分建议,但没有一个对我有用,所以我想出了自己的正则表达式,据我所知,它捕获了截至1月13日的所有有效的英国邮政编码(根据皇家邮政的最新文献)。

The regex and some simple postcode checking PHP code is posted below. NOTE:- It allows for lower or uppercase postcodes and the GIR 0AA anomaly but to deal with the, more than likely, presence of a space in the middle of an entered postcode it also makes use of a simple str_replace to remove the space before testing against the regex. Any discrepancies beyond that and the Royal Mail themselves don't even mention them in their literature (see http://www.royalmail.com/sites/default/files/docs/pdf/programmers_guide_edition_7_v5.pdf and start reading from page 17)!

注意:在皇家邮政自己的文献中(链接以上),第3和第4位的位置略有模糊,如果这些字符是字母,则例外。我直接联系了皇家邮政,用他们自己的话说,“AANA NAA格式的出境代码的第4个位置的信件没有例外,而第3个位置的例外只适用于ANA NAA格式的出境代码的最后一个字母。”直接从马嘴里说出来的!

<?php

    $postcoderegex = '/^([g][i][r][0][a][a])$|^((([a-pr-uwyz]{1}([0]|[1-9]\d?))|([a-pr-uwyz]{1}[a-hk-y]{1}([0]|[1-9]\d?))|([a-pr-uwyz]{1}[1-9][a-hjkps-uw]{1})|([a-pr-uwyz]{1}[a-hk-y]{1}[1-9][a-z]{1}))(\d[abd-hjlnp-uw-z]{2})?)$/i';

    $postcode2check = str_replace(' ','',$postcode2check);

    if (preg_match($postcoderegex, $postcode2check)) {

        echo "$postcode2check is a valid postcode<br>";

    } else {

        echo "$postcode2check is not a valid postcode<br>";

    }

?>

我希望它能帮助其他遇到这条线索寻找解决方案的人。

虽然这里有很多答案,但我对其中任何一个都不满意。他们中的大多数只是简单地坏了,太复杂或只是坏了。

我看了@ctwheels的答案,我发现它非常具有解释性和正确性;我们必须为此感谢他。然而,对我来说,如此简单的事情又有太多的“数据”了。

幸运的是,我设法获得了一个数据库,其中仅包含英国的100多万个活动邮政编码,并编写了一个小型PowerShell脚本来测试和基准测试结果。

英国邮政编码规格:有效的邮政编码格式。

这是“我的”正则表达式:

^([a-zA-Z]{1,2}[a-zA-Z\d]{1,2})\s(\d[a-zA-Z]{2})$

简短,简单,甜蜜。即使是最没有经验的人也能明白发生了什么。

解释:

^ asserts position at start of a line
    1st Capturing Group ([a-zA-Z]{1,2}[a-zA-Z\d]{1,2})
        Match a single character present in the list below [a-zA-Z]
        {1,2} matches the previous token between 1 and 2 times, as many times as possible, giving back as needed (greedy)
        a-z matches a single character in the range between a (index 97) and z (index 122) (case sensitive)
        A-Z matches a single character in the range between A (index 65) and Z (index 90) (case sensitive)
        Match a single character present in the list below [a-zA-Z\d]
        {1,2} matches the previous token between 1 and 2 times, as many times as possible, giving back as needed (greedy)
        a-z matches a single character in the range between a (index 97) and z (index 122) (case sensitive)
        A-Z matches a single character in the range between A (index 65) and Z (index 90) (case sensitive)
        \d matches a digit (equivalent to [0-9])
        \s matches any whitespace character (equivalent to [\r\n\t\f\v ])
    2nd Capturing Group (\d[a-zA-Z]{2})
        \d matches a digit (equivalent to [0-9])
        Match a single character present in the list below [a-zA-Z]
        {2} matches the previous token exactly 2 times
        a-z matches a single character in the range between a (index 97) and z (index 122) (case sensitive)
        A-Z matches a single character in the range between A (index 65) and Z (index 90) (case sensitive)
$ asserts position at the end of a line

结果(已核对邮编):

TOTAL OK: 1469193
TOTAL FAILED: 0
-------------------------------------------------------------------------
Days              : 0
Hours             : 0
Minutes           : 5
Seconds           : 22
Milliseconds      : 718
Ticks             : 3227185939
TotalDays         : 0.00373516891087963
TotalHours        : 0.0896440538611111
TotalMinutes      : 5.37864323166667
TotalSeconds      : 322.7185939
TotalMilliseconds : 322718.5939
^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$

Regular expression to match valid UK postcodes. In the UK postal system not all letters are used in all positions (the same with vehicle registration plates) and there are various rules to govern this. This regex takes into account those rules. Details of the rules: First half of postcode Valid formats [A-Z][A-Z][0-9][A-Z] [A-Z][A-Z][0-9][0-9] [A-Z][0-9][0-9] [A-Z][A-Z][0-9] [A-Z][A-Z][A-Z] [A-Z][0-9][A-Z] [A-Z][0-9] Exceptions Position - First. Contraint - QVX not used Position - Second. Contraint - IJZ not used except in GIR 0AA Position - Third. Constraint - AEHMNPRTVXY only used Position - Forth. Contraint - ABEHMNPRVWXY Second half of postcode Valid formats [0-9][A-Z][A-Z] Exceptions Position - Second and Third. Contraint - CIKMOV not used

http://regexlib.com/REDetails.aspx?regexp_id=260