使用sapply和grepl将向量匹配到多个字符串时添加标记

时间:2016-07-26 13:42:13

标签: regex r sapply grepl

我正在尝试检查包含许多元素的向量与包含字符串的数据框列之间的匹配。

vec <- c("KIND", "Quest")

string <- ("lieberkind", "kind", "KIND", "Quest Nutrition", "Quest")

x <- sapply(vec, function (x) grepl(x, string, ignore.case = TRUE))

结果如下:

> x
      KIND Quest
[1,]  TRUE FALSE
[2,]  TRUE FALSE
[3,]  TRUE FALSE
[4,] FALSE  TRUE
[5,] FALSE  TRUE

问题在于“KIND”的第一个结果,它最终为'lieberkind'生成一个TRUE值。

通常情况下,我会添加一个令牌来指定字边界,如:

grepl("\\bKIND\\b", string, ignore.case = TRUE)
[1] FALSE  TRUE  TRUE FALSE FALSE

但是当我使用sapply将向量的每个元素与字符串的每个元素进行比较时,我不知道如何做到这一点。

我显然不能这样做:

x <- sapply(vec, function (x) grepl(\\bx\\b, string, ignore.case = TRUE))

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

有多种方法可以检查字边界,它们取决于您的数据。如果您需要使用单词边界,请使用

x <- sapply(vec, function (x) grepl(paste0("\\b",x,"\\b"), string, ignore.case = TRUE))

Jota's recommended equivalent

x <- sapply(vec, function (x) grepl(sprintf("\\b%s\\b", x), string, ignore.case = TRUE))

但是,如果您的vec包含内部带有特殊字符的条目(注意:不在开头或结尾),那么您需要使用

之类的东西来转义它们
x <- sapply(vec, function (x) grepl(paste0("\\b",gsub("([][/\\\\^$*+?.()|{}-])", "\\\\\\1", x),"\\b"), string, ignore.case = TRUE))

最后,如果你将单词边界定义为空白字符串或字符串的开头/结尾,我宁愿推荐一个像

这样的PCRE正则表达式
x <- sapply(vec, function (x) grepl(paste0("(?<!\\S)",gsub("([][/\\\\^$*+?.()|{}-])", "\\\\\\1", x),"(?!\\S)"), string, ignore.case = TRUE, perl=TRUE))

测试数据的所有3个案例的结果如下:

      KIND Quest
[1,] FALSE FALSE
[2,]  TRUE FALSE
[3,]  TRUE FALSE
[4,] FALSE  TRUE
[5,] FALSE  TRUE

P.S。无论您使用paste0还是sprintf,都会得到相同的结果。