为了从 R 中的变量构建正则表达式,在当前场景中,您可以使用 paste0 简单地将字符串文字与变量连接:: p>
grep(paste0('\\{', n, '} number'), homicides, value=TRUE)
请注意,{ 是[...] 括号表达式(也称为字符类)之外的特殊字符,如果您需要查找文字{ 字符,则应进行转义。
如果您使用项目列表作为替代列表,您可以使用paste/paste0的组合:
words <- c('bananas', 'mangoes', 'plums')
regex <- paste0('Ben likes (', paste(words, collapse='|'), ')\\.')
生成的Ben likes (bananas|mangoes|plums)\. 正则表达式将匹配Ben likes bananas.、Ben likes mangoes. 或Ben likes plums.。请参阅R demo 和regex demo。
注意:PCRE(当您将 perl=TRUE 传递给基本 R 正则表达式函数时)或 ICU(stringr/stringi 正则表达式函数)具有证明可以更好地处理这些场景,建议使用这些引擎而不是基本 R 正则表达式函数中使用的默认 TRE 正则表达式库。
通常,您会希望构建一个包含应完全匹配的单词列表的模式,作为整个单词。在这里,很大程度上取决于边界的类型以及单词是否可以包含特殊的正则表达式元字符,它们是否可以包含空格。
在最一般的情况下,word boundaries (\b) 运行良好。
regex <- paste0('\\b(', paste(words, collapse='|'), ')\\b')
unlist(regmatches(examples, gregexpr(regex, examples, perl=TRUE)))
## => [1] "bananas" "mangoes" "plums"
\b(bananas|mangoes|plums)\b 模式将匹配 bananas,但匹配 won't match banana(参见 R demo)。
如果你的列表是这样的
words <- c('cm+km', 'uname\\vname')
您必须先对单词进行转义,即在每个元字符之前附加\:
regex.escape <- function(string) {
gsub("([][{}()+*^$|\\\\?.])", "\\\\\\1", string)
}
examples <- c('Text: cm+km, and some uname\\vname?')
words <- c('cm+km', 'uname\\vname')
regex <- paste0('\\b(', paste(regex.escape(words), collapse='|'), ')\\b')
cat( unlist(regmatches(examples, gregexpr(regex, examples, perl=TRUE))) )
## => cm+km uname\vname
如果您的单词可以以特殊的正则表达式元字符开头或结尾,\b 单词边界将不起作用。使用
-
明确的单词边界,
(?<!\w) / (?!\w),当非单词字符或字符串的开头/结尾预期匹配时
-
空白边界,
(?<!\S) / (?!\S),当匹配被期望用空白字符或字符串的开头/结尾括起来时
- 使用lookbehind/lookahead 组合和您的自定义字符类/括号表达式构建您自己的,甚至更复杂的模式。
first two approaches in R 示例(替换为 << 和 >> 括起来的匹配项):
regex.escape <- function(string) {
gsub("([][{}()+*^$|\\\\?.])", "\\\\\\1", string)
}
examples <- 'Text: cm+km, +km and C++,Delphi,C++CLI and C++/CLI.'
words <- c('+km', 'C++')
# Unambiguous word boundaries
regex <- paste0('(?<!\\w)(', paste(regex.escape(words), collapse='|'), ')(?!\\w)')
gsub(regex, "<<\\1>>", examples, perl=TRUE)
# => [1] "Text: cm+km, <<+km>> and <<C++>>,Delphi,C++CLI and <<C++>>/CLI."
# Whitespace boundaries
regex <- paste0('(?<!\\S)(', paste(regex.escape(words), collapse='|'), ')(?!\\S)')
gsub(regex, "<<\\1>>", examples, perl=TRUE)
# => [1] "Text: cm+km, <<+km>> and C++,Delphi,C++CLI and C++/CLI."