正则表达式提取美国邮政编码但不提取伪代码

law*_*yeR 5 regex string r

使用 XML 包和 XPath 从网站抓取地址,有时我只能得到一个字符串,其中嵌入了我想要的邮政编码。提取邮政编码很简单,但有时会显示其他五位数的字符串。

以下是 df 中问题的一些变体。

zips <- data.frame(id = seq(1, 5), address = c("Company, 18540 Main Ave., City, ST 12345", "Company 18540 Main Ave. City ST 12345-0000", "Company 18540 Main Ave. City State 12345", "Company, 18540 Main Ave., City, ST 12345 USA", "Company, One Main Ave Suite 18540, City, ST 12345")) 
Run Code Online (Sandbox Code Playgroud)

下面是提取邮政编码(5 位和 4 位数字)的 R 语句,但它被街道号码和套房号的虚假邮政编码所欺骗(其他地址字符串中可能还有其他可能性)。

regmatches(zips$address, gregexpr("\\d{5}([-]?\\d{4})?", zips$address, perl = TRUE))
Run Code Online (Sandbox Code Playgroud)

对上一个 SO 问题的回答表明“正则表达式将返回最后一个连续的五位数字字符串。它使用负前瞻来确保在返回后没有 5 位数字字符串。”
从地址字符串中提取邮政编码

\b\d{5}\b(?!.*\b\d{5}\b)
Run Code Online (Sandbox Code Playgroud)

但是这个问题和答案涉及 PHP,并提供了一个带有 preg_matches()` 的 if 循环我不熟悉这些语言和工具,但这个想法可能是正确的。

我的问题:什么 R 代码会找到真正的邮政编码并忽略虚假的相似之处?

raw*_*awr 4

这是我的第一个正则表达式答案(我仍在学习),所以希望我不会说任何错误的话来引导您走向错误的方向。

基本上,正如您在问题中暗示的那样,这个正则表达式会查找最后一个看起来像邮政编码的字符串,该字符串后面不跟有看起来像邮政编码的字符串

基本语法是,仅当后面没有任何内容(否定的前瞻断言,语法:)时才pattern(?!.*pattern)匹配并且pattern(?! ) .* pattern

所以我们可以用您感兴趣的内容替换模式:

[0-9]{5}(-[0-9]{4})?

也就是说,[0-9]正好 5 个字符的数字字符串{5}(可以选择后跟?定义为连字符的另一组和另一个长度为 4 的数字字符串)(-[0-9]{4})

将所有内容放在一起gregexpr搜索匹配项并regmatches为我解释结果,我得到:

zips <- data.frame(id = seq(1, 5), address = c("Company, 18540 Main Ave., City, ST 12345", "Company 18540 Main Ave. City ST 12345-0000", "Company 18540 Main Ave. City State 12345", "Company, 18540 Main Ave., City, ST 12345 USA", "Company, One Main Ave Suite 18540, City, ST 12345")) 
regmatches(zips$address,
           gregexpr('[0-9]{5}(-[0-9]{4})?(?!.*[0-9]{5}(-[0-9]{4})?)', zips$address, perl = TRUE))

# [[1]]
# [1] "12345"
# 
# [[2]]
# [1] "12345-0000"
# 
# [[3]]
# [1] "12345"
# 
# [[4]]
# [1] "12345"
# 
# [[5]]
# [1] "12345"
Run Code Online (Sandbox Code Playgroud)