gpt4 book ai didi

r 用于从地址中提取英国邮政编码的正则表达式未排序

转载 作者:行者123 更新时间:2023-12-01 09:13:28 24 4
gpt4 key购买 nike

我正在尝试使用英国政府 here 提供的正则表达式从 R 中的地址字符串中提取英国邮政编码。

这是我的功能:

address_to_postcode <- function(addresses) {

# 1. Convert addresses to upper case
addresses = toupper(addresses)

# 2. Regular expression for UK postcodes:
pcd_regex = "[Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) {0,1}[0-9][A-Za-z]{2})"

# 3. Check if a postcode is present in each address or not (return TRUE if present, else FALSE)
present <- grepl(pcd_regex, addresses)

# 4. Extract postcodes matching the regular expression for a valid UK postcode
postcodes <- regmatches(addresses, regexpr(pcd_regex, addresses))

# 5. Return NA where an address does not contain a (valid format) UK postcode
postcodes_out <- list()
postcodes_out[present] <- postcodes
postcodes_out[!present] <- NA

# 6. Return the results in a vector (should be same length as input vector)
return(do.call(c, postcodes_out))
}

根据指导文档,这个正则表达式查找的逻辑如下:

"GIR 0AA" OR One letter followed by either one or two numbers OR One letter followed by a second letter that must be one of ABCDEFGHJ KLMNOPQRSTUVWXY (i.e..not I) and then followed by either one or two numbers OR One letter followed by one number and then another letter OR A two part post code where the first part must be One letter followed by a second letter that must be one of ABCDEFGH JKLMNOPQRSTUVWXY (i.e..not I) and then followed by one number and optionally a further letter after that AND The second part (separated by a space from the first part) must be One number followed by two letters. A combination of upper and lower case characters is allowed. Note: the length is determined by the regular expression and is between 2 and 8 characters.



我的问题是,在使用没有 ^$ anchor 的正则表达式时,这个逻辑没有完全保留(在这种情况下我必须这样做,因为邮政编码可能在地址字符串中的任何位置);我正在努力解决的是如何在部分(而不是完整)字符串匹配中保留每个段的顺序和字符数。

考虑以下示例:
> address_to_postcode("1A noplace road, random city, NR1 2PK, UK")
[1] "NR1 2PK"

根据指南中的逻辑,邮政编码中的第二个字母不能是“z”(还有一些其他排除项);但是看看当我添加一个“z”时会发生什么:
> address_to_postcode("1A noplace road, random city, NZ1 2PK, UK")
[1] "Z1 2PK"

...而在这种情况下,我希望输出为 NA

添加 anchor (对于不同的用例)似乎没有帮助,因为即使“z”位于错误的位置,它仍然被接受:
> grepl("^[Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) {0,1}[0-9][A-Za-z]{2})$", "NZ1 2PK")
[1] TRUE

两个问题:
  • 是不是我误解了正则表达式和
  • 的逻辑
  • 如果不是,我该如何更正(即为什么不是指定的字母
    和字符范围专属于它们在正则表达式中的位置)?
  • 最佳答案

    编辑

    自从发布这个答案后,我深入研究了英国政府的正则表达式,发现了更多问题。 I posted another answer here 描述了所有问题,并为格式不佳的正则表达式提供了替代方案。

    笔记

    请注意,我在这里发布了原始正则表达式。移植到 时,您需要转义某些字符(如反斜杠 \ )。

    问题

    您在这里有很多问题,所有这些问题都是由创建您从中检索正则表达式的文档的人或创建它的编码人员引起的。

    1.空格符

    我的猜测是,当您从提供的链接复制正则表达式时,它将空格字符转换为换行符并将其删除(这正是我最初所做的)。相反,您需要将其更改为空格字符。

    ^([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})$
    here ^

    2. 边界

    您需要删除 anchor ^$,因为它们指示行的开始和结束。相反,将您的正则表达式包装在 (?:) 中,并在任一端放置一个 \b(字边界),如下所示。事实上,文档中的正则表达式是不正确的(有关更多信息,请参阅 旁注 ),因为它无法正确 anchor 定模式。

    See regex in use here
    \b(?:([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([AZa-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2}))\b
    ^^^^^ ^^^

    3.字符类监督

    正如 @deadcrab 在他的回答 here 中指出的那样,字符类中缺少 -
    \b(?:([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2}))\b
    ^

    4. 他们将错误的字符类设为可选!

    在文档中 清楚地 声明:

    A two part post code where the first part must be:

    • One letter followed by a second letter that must be one of ABCDEFGHJKLMNOPQRSTUVWXY (i.e..not I) and then followed by one number and optionally a further letter after that


    他们将错误的字符类设为可选!
    \b(?:([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2}))\b
    ^^^^^^
    it should be this one ^^^^^^^^

    5.整件事太糟糕了......

    这个正则表达式有很多问题,我决定重写它。它可以很容易地简化为执行当前匹配文本所需的一小部分步骤。
    \b(?:[A-Za-z][A-HJ-Ya-hj-y]?[0-9][0-9A-Za-z]? [0-9][A-Za-z]{2}|[Gg][Ii][Rr] 0[Aa]{2})\b

    回答

    正如我的回答下面的评论中提到的,一些邮政编码缺少空格字符。对于邮政编码中缺少的空格(例如 NR12PK ),只需在空格后添加 ? ,如下面的正则表达式所示:
    \b(?:[A-Za-z][A-HJ-Ya-hj-y]?[0-9][0-9A-Za-z]? ?[0-9][A-Za-z]{2}|[Gg][Ii][Rr] ?0[Aa]{2})\b
    ^^ ^^

    您还可以使用以下内容缩短上面的正则表达式并使用不区分大小写的标志( 中的 ignore.case(pattern)ignore_case = TRUE ,取决于所使用的方法。):
    \b(?:[A-Z][A-HJ-Y]?[0-9][0-9A-Z]? ?[0-9][A-Z]{2}|GIR ?0A{2})\b

    笔记

    请注意,正则表达式仅验证字符串的可能格式,而不能实际识别邮政编码是否合法存在。为此,您应该使用 API。还有一些边缘情况,这个正则表达式不能正确匹配有效的邮政编码。有关这些邮政编码的列表,请参阅此 Wikipedia article

    下面的正则表达式还匹配以下内容(使其不区分大小写以匹配小写变体):
  • 英国海外领土
  • 英国军队邮局
  • 尽管他们最近将其更改为与英国邮政编码系统保持一致,为 BF ,后跟一个数字(以 BF1 开头),但它们被认为是可选的替代邮政编码
  • 那篇文章中概述的特殊情况(以及 SAN TA1 - 圣诞老人的有效邮政编码!)

  • See this regex in use here
    \b(?:(?:[A-Z][A-HJ-Y]?[0-9][0-9A-Z]?|ASCN|STHL|TDCU|BBND|[BFS]IQ{2}|GX11|PCRN|TKCA) ?[0-9][A-Z]{2}|GIR ?0A{2}|SAN ?TA1|AI-?[0-9]{4}|BFPO[ -]?[0-9]{2,3}|MSR[ -]?1(?:1[12]|[23][135])0|VG[ -]?11[1-6]0|[A-Z]{2} ? [0-9]{2}|KY[1-3][ -]?[0-2][0-9]{3})\b

    我还建议任何实现此答案的人阅读 this StackOverflow question titled UK Postcode Regex (Comprehensive)

    边注

    您链接到的文档( Bulk Data Transfer: Additional Validation for CAS Upload - Section 3. UK Postcode Regular Expression )实际上有一个不正确的正则表达式。

    正如 问题 部分所述,它们应该具有:
  • 将整个表达式包裹在 (?:) 中,并将 anchor 放置在非捕获组周围。他们的正则表达式,就目前而言,在某些情况下会失败,如 here 所示。
  • 正则表达式在字符类
  • 之一中也缺少 -
  • 它还使错误的字符类成为可选的。
  • 关于r 用于从地址中提取英国邮政编码的正则表达式未排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51828712/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com