在R中用正则表达式精确匹配任意数量的字符

3

我想使用正则表达式来计算字符的确切连续出现次数。例如,让模式为"aa""bbb",即"a"恰好连续出现两次的次数;"b"恰好连续出现三次的次数(它们可以在前后由任何字符包围,包括没有字符,除了该字符本身)。如果测试向量是:

c("baa", "aaaa", "aab", "aa", "bbba", "bbaabbb")

计数结果应该如下所示:

enter image description here

匹配模式为"aa"的有c("baa", "aab", "aa", "bbaabbb")&

匹配模式为"bbb"的有c("bbba", "bbaabbb")

我已经使用了"\\<"&"\\>",但并没有得到我想要的结果。如果能提供任何帮助,我将不胜感激。


请分享您用于测试的代码。 - Wiktor Stribiżew
你是否一定要使用“regex”包?因为你可以用“stringr”包完成这个任务。vec <- c("baa", "aaaa", "aab", "aa", "bbba", "bbaabbb"); count_aa <- sum(str_detect(vec,'aa')) 等等… - Smich7
@Smich,我知道stringr。它将无法忽略可以由任何字符(包括仅由字符本身)限定的条件。我认为正则表达式是唯一的解决方法。 - Tunde Awosanya
2个回答

7
要匹配恰好出现两次的字符“a”,您可以使用负回顾结合负前瞻。也就是说,您在寻找一个位置,
  • 不跟随一个字符“a”,
  • 包含字符串“aa”,并且
  • 不跟随一个“a”
所使用的正则表达式是(?<!a)a{2}(?!a)示例:
test <- c("baa", "aaaa", "aab", "aa", "bbba", "bbaabbb")
grep("(?<!a)a{2}(?!a)", test, perl = TRUE, value = TRUE)
# [1] "baa"     "aab"     "aa"      "bbaabbb"

类似地,匹配恰好出现三次字符“b”的方法如下:

grep("(?<!b)b{3}(?!b)", test, perl = TRUE, value = TRUE)
# [1] "bbba"    "bbaabbb"

0

我们还可以分割并获取表格

 table(unlist(lapply(strsplit(v1, "(?<=b)(?=a)|(?<=a)(?=b)", perl =TRUE), 
            function(x) x[x %in% c('aa', 'bbb')])))
 # aa bbb 
 # 4   2 

如果有其他字符,

table(unlist(lapply(strsplit(v2, "(?<=[^a])(?=a)|(?<=a)(?!a)",
         perl = TRUE), function(x) x[x %in% c('aa', 'bbb')])))
# aa bbb 
#  5   2 

数据

v1 <- c("baa", "aaaa", "aab", "aa", "bbba", "bbaabbb")
v2 <- c("baa", "aaaa", "aab", "aa", "bbba", "bbaabbb", "caa")

这是否假设字符串仅包含字母"a"和"b"?这种方法是否无法匹配"caa"? - ikop
1
抱歉,我不是要贬低你的回答。我认为strsplit非常优雅。我只是想知道这种方法是否能够捕获字符串“caa”中的“aa”(*...它们可以被任何字符包围,包括什么都没有,除了字符本身*)。 - ikop
是的,Ikop,它不仅包含a和b。谢谢Akrun的努力,但我不确定这种方法是否稳健。如果我想检查长度从1到10,我将不得不手动输入我想要的所有模式,例如“aa”,“aaa”,“aaaa”等,但使用Ikop的方法,我可以轻松地结合for循环length函数来知道a或b的1,2,3 ...出现次数的数量。也许如果您可以使其更易于推广而不是具体化。 - Tunde Awosanya
@TundeAwosanya 关于您的评论,table(unlist(lapply(strsplit(v2, "(?<=[^a])(?=a)|(?<=a)(?!a)",perl = TRUE), function(x) Map(function(y, z) x[x %in% c(y, z)], c('aa', 'aaa', 'aaaa'), c('bb', 'bbb', 'bbbb'))))) 可以得到您想要的输出。 - akrun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接