我正在尝试从字符串中删除/提取邮政编码。逻辑是我抓住的东西:
字符串的zip部分可以以空格开头,但可能不是。
这是一个MWE和我尝试过的。 2个尝试的正则表达式基于this question和this question:
text.var <- c("Mr. Bean bought 2 tickets 2-613-213-4567",
"43 Butter Rd, Brossard QC K0A 3P0 – 613 213 4567",
"Rat Race, XX, 12345",
"Ignore phone numbers(613)2134567",
"Grab zips with dashes 12345-6789 or no space before12345-6789",
"Grab zips with spaces 12345 6789 or no space before12345 6789",
"I like 1234567 dogs"
)
pattern1 <- "\\d{5}([- ]*\\d{4})?"
pattern2 <- "[0-9]{5}(-[0-9]{4})?(?!.*[0-9]{5}(-[0-9]{4})?)"
regmatches(text.var, gregexpr(pattern1, text.var, perl = TRUE))
regmatches(text.var, gregexpr(pattern2, text.var, perl = TRUE))
## [[1]]
## character(0)
##
## [[2]]
## character(0)
##
## [[3]]
## [1] "12345"
##
## [[4]]
## [1] "21345"
##
## [[5]]
## [1] "12345-6789"
##
## [[6]]
## [1] "12345"
##
## [[7]]
## [1] "12345"
所需输出
## [[1]]
## character(0)
##
## [[2]]
## character(0)
##
## [[3]]
## [1] "12345"
##
## [[4]]
## character(0)
##
## [[5]]
## [1] "12345-6789" "12345-6789"
##
## [[6]]
## [1] "12345 6789" "12345 6789"
##
## [[7]]
## character(0)
注意 R的正则表达式与其他正则表达式类似但是特定于R。这个问题特定于R的正则表达式而不是一般的正则表达式问题。
答案 0 :(得分:2)
答案 1 :(得分:2)
这对我有用,并为您的所有示例提供了所需的输出:
"(?<!\\d)(\\d{5}(?:[- ]\\d{4})?)(?!\\d)"
答案 2 :(得分:2)
您可以在此处使用Negative Lookbehind和字边界\b
的组合。
regmatches(text.var, gregexpr('(?<!\\d)\\d{5}(?:[ -]\\d{4})?\\b', text.var, perl=T))
<强>解释强>:
Word边界断言,一方面有一个单词字符,另一方面没有。
(?<! # look behind to see if there is not:
\d # digits (0-9)
) # end of look-behind
\d{5} # digits (0-9) (5 times)
(?: # group, but do not capture (optional):
[ -] # any character of: ' ', '-'
\d{4} # digits (0-9) (4 times)
)? # end of grouping
\b # the boundary between a word character (\w) and not a word character
您可以考虑使用速度更快的stringi
库包。
> library(stringi)
> stri_extract_all_regex(text.var, '(?<!\\d)\\d{5}(?:[ -]\\d{4})?\\b')
答案 3 :(得分:1)
(?<![0-9-])([0-9]{5}(?:[ -][0-9]{4})?)(?![0-9-])`
现场演示:http://regex101.com/r/hU9oK4/1
我们之后的事情:
[0-9]{5}
是重要的部分,正好找5位数字
(?:[ -][0-9]{4})?)
只有在用空格或减号连接的情况下才可选择再加4次
边界,边界,边界:
(?<![0-9-])
第一组:负面LookBehind(确保没有数字或短划线)
(?![0-9-])
最后一组:负面预测( - || - 相同模式...... )
额外的测试用例:
另一个拉链09788-4234后没有空格 98712个
987122个
邮编或范围12987-19222?
这个系列怎么样88101-8892-22912-9991-99101?
90872-8881
consume
个字符最终说明:这不是 最终 或防弹匹配代码,您可能仍会收集一些zip相似内容,尤其是因为您需求中数字组之间的空格
个人注意事项我发现[0-9]
个字符类更清晰且更易于理解适用于RegEx的新手,即使他们已包含在一个\d
,但它们也更快,并且在RegEx风格之间具有更好的兼容性。另一方面,双重逃避(例如\\d
是丑陋的阅读)
答案 4 :(得分:0)
qdapRegex
包具有rm_zip
功能(基于@ hwnd&#39; s响应):
rm_zip(text.var)
rm_zip(text.var, extract=TRUE)
> rm_zip(text.var, extract=TRUE)
[[1]]
[1] NA
[[2]]
[1] NA
[[3]]
[1] "12345"
[[4]]
[1] NA
[[5]]
[1] "12345-6789" "12345-6789"
[[6]]
[1] "12345 6789" "12345 6789"
[[7]]
[1] NA