如何修改此正则表达式以提取英国邮政编码的左手和右手部分?

时间:2009-03-26 15:08:49

标签: .net regex

我有一个正则表达式,用于验证英国邮政编码,但现在我想提取代码的组成部分,我感到困惑。对于那些不知道英国邮政编码的例子的人是'WC1 1AA','WC11 1AA'和'M1 1AA'。

下面的正则表达式(格式化道歉)处理左侧和右侧部分之间缺少空格(这是\s{0,}位)并且仍然有效(这很好)。

(?:(?:A[BL]|B[ABDHLNRST]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[CHNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTWY]?|T[ADFNQRSW]|UB|W[ACDFNRSV]?|YO|ZE)\d(?:\d|[A-Z])?\s{0,}\d[A-Z]{2})

我希望能够现在提取左侧和右侧,我知道括号用于此,但是已经有括号,并且正则表达式规范不容易阅读。所以我想这些括号需要更换,有人可以帮我修改括号吗?

我可以看到其他人会发现这个使用正则表达式,所以请随意使用它来验证英国邮政地址。

3 个答案:

答案 0 :(得分:5)

实际上,括号用于提取,而不是括号。 (?:表达式中的结构是阻止括号执行提取的方式。您可能需要:

(?:((?:A[BL]|B[ABDHLNRST]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[CHNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTWY]?|T[ADFNQRSW]|UB|W[ACDFNRSV]?|YO|ZE)\d(?:\d|[A-Z])?)\s{0,}(\d[A-Z]{2}))

顺便说一下,我也会做出这样的改变:

(?:((?:A[BL]|B[ABDHLNRST]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[CHNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTWY]?|T[ADFNQRSW]|UB|W[ACDFNRSV]?|YO|ZE)\d(?:\d|[A-Z])?)\s*(\d[A-Z]{2}))

因为 \ s {0,} 是一种愚蠢的方式来写 \ s *

答案 1 :(得分:4)

此外,我建议不要试图彻底检查邮政编码。有效邮政编码列表可以更改,因此每次邮局更新PAF时都必须维护表达式。

你也错过了一些像BFPO,GIR,非地理邮政编码和海外领土这样的“特殊邮政编码”。有关您可能需要处理的内容的概述,请参阅wiki

一般来说,对于大多数用途来说,“它看起来似乎有道理吗?”检查比试图完全确定它更好。没有什么比告诉客户他们不能使用您的服务更糟糕了,因为他们的地址不存在。

答案 2 :(得分:1)

在处理像这样的大型正则表达式时,你应该使用/x选项(我认为在C#中称为RegexOptions.IgnorePatternWhitespace)。 (?:)没有捕获,所以你需要做的就是将()放在你想要的部分周围。 /x选项的另一个好处是,您可以使用行尾注释(它们以#开头)对正则表达式进行注释。您可能还需要注意\ d和\ s。它们可能匹配的次数超出预期(\s匹配所有空格,而不仅仅是空格,至少在Perl 5.8及更高版本中,\d匹配所有UNICODE数字字符,而不仅仅是[0-9])< / p>

Regex exp = new Regex(@"
    (?:
        ( #capture first part
            (?:
                A[BL]        | B[ABDHLNRST]? | C[ABFHMORTVW]      |
                D[ADEGHLNTY] | E[CHNX]?      | F[KY]              |
                G[LUY]?      | H[ADGPRSUX]   | I[GMPV]            |
                JE           | K[ATWY]       | L[ADELNSU]?        |
                M[EKL]?      | N[EGNPRW]?    | O[LX]              |
                P[AEHLOR]    | R[GHM]        | S[AEGKLMNOPRSTWY]? |
                T[ADFNQRSW]  | UB            | W[ACDFNRSV]?       |
                YO           | ZE
            )
            \d
            (?:
                \d | [A-Z]
            )?
        ) #end capture of first part
        \s{0,}
        ( #capture second part
            \d[A-Z]{2}
        ) #end capture of second part
    )",
    RegexOptions.IgnorePatternWhitespace
);