我有一个字符串向量:
s <- c('abc1', 'abc2', 'abc3', 'abc11', 'abc12',
'abcde1', 'abcde2', 'abcde3', 'abcde11', 'abcde12',
'nonsense')
我希望正则表达式仅匹配以abc
开头并以3
,11
或12
结尾的字符串。换句话说,正则表达式必须排除abc1
但不排除abc11
,abc2
但不排除abc12
,依此类推。
我认为使用前瞻断言很容易做到这一点,但我找不到办法。有吗?
编辑:感谢下面的海报,指出原帖中的严重歧义。
实际上,我有很多字符串。它们都以数字结尾:一些在0中,一些在9中,一些在数字之间。我正在寻找一个匹配所有字符串的正则表达式,除了那些以字母后跟1或2结尾的字符串。(正则表达式也应该只匹配那些以abc
开头的字符串,但这是一个简单的问题。)
我尝试使用负前瞻断言来创建这样的正则表达式。但我没有任何成功。
感谢所有回复和评论的人。受到你们几个人的启发,我最终使用了这个组合:grepl('^abc', s) & !grepl('[[:lower:]][12]$', s)
。
答案 0 :(得分:3)
这是你想要的吗?
s[grepl("abc.*(3|11|12)", s)]
[1] "abc3" "abc11" "abc12" "abcde3" "abcde11" "abcde12"
排除的字符串是:
s[!grepl("abc.*(3|11|12)", s)]
[1] "abc1" "abc2" "abcde1" "abcde2" "nonsense"
编辑:正如评论所示,您的要求存在一些歧义。更全面的正则表达式将测试字符串开始^
和字符串结束$
,并且可能只允许字母字符[[:alpha:]]
在最终数字之前:
s[grepl("^abc[[:alpha:]]*.*(3|11|12)$", s)]
[1] "abc3" "abc11" "abc12" "abcde3" "abcde11" "abcde12"
您还可以通过传递参数grep
让value=TRUE
直接返回值,从而在代码中保存一些重复:
grep("^abc[[:alpha:]]*.*(3|11|12)$", s, value=TRUE)
[1] "abc3" "abc11" "abc12" "abcde3" "abcde11" "abcde12"
答案 1 :(得分:3)
在这种情况下,我认为使用两个简单的正则表达式更容易,而不是一个复杂的正则表达式:
s <- c('abc1', 'abc2', 'abc3', 'abc11', 'abc12',
'abcde1', 'abcde2', 'abcde3', 'abcde11', 'abcde12',
'nonsense')
s[grepl("^abc", s) & grepl("(3|11|12)$", s)]
答案 2 :(得分:1)
在这种情况下你也可以使用substring
:
z <- nchar(s)
s[substring(s, 1, 3) == "abc" & substring(s, z) == "3" |
substring(s, z-1) %in% c("12", "11")]
答案 3 :(得分:0)
专门查看所要求的数字,即可:
n <- c(3,11,12)
s[sub('abc[^[:digit:]]*([[:digit:]]+)$',s, replacement='\\1') %in% n]
[1] "abc3" "abc11" "abc12" "abcde3" "abcde11" "abcde12"
这不会混淆11 for 1:
n <- c(3,1,12)
s[sub('abc[^[:digit:]]*([[:digit:]]+)$',s, replacement='\\1') %in% n]
[1] "abc1" "abc3" "abc12" "abcde1" "abcde3" "abcde12"
对于您的编辑,不以1或2结尾(并使用两个正则表达式)
s[grepl('^abc',s) & !(sub('.*[^[:digit:]]([[:digit:]]+)$',s, replacement='\\1') %in% c(1,2))]
[1] "abc3" "abc11" "abc12" "abcde3" "abcde11" "abcde12"