【问题标题】:Using variable to create regular expression pattern in R使用变量在 R 中创建正则表达式模式
【发布时间】:2013-01-30 12:44:08
【问题描述】:

我有一个函数:

ncount <- function(num = NULL) {

 toRead <- readLines("abc.txt")
 n <- as.character(num)
 x <- grep("{"n"} number",toRead,value=TRUE)

}

在 grep-ing 时,我希望函数中传递的 num 动态创建要搜索的模式?如何在 R 中做到这一点?文本文件的每一行都有数字和文本

【问题讨论】:

  • 这里的最佳实践是使用包含在 R 包中的简单数据集创建一个可用的示例,以及我们都可以粘贴并使其工作的代码。您的问题不包含任何内容(一方面,我们没有您的“abc.txt”文件)。
  • 感谢@Spacedman;将来会照顾同样的事情。

标签: regex r pattern-matching


【解决方案1】:

您可以使用paste 连接字符串:

grep(paste("{", n, "} number", sep = ""),homicides,value=TRUE)

【讨论】:

  • paste0 将为您节省一些手指操:paste0("{", n, "} number")
【解决方案2】:

为了从 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 demoregex 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 单词边界将不起作用。使用

  • 明确的单词边界(?&lt;!\w) / (?!\w),当非单词字符或字符串的开头/结尾预期匹配时
  • 空白边界(?&lt;!\S) / (?!\S),当匹配被期望用空白字符或字符串的开头/结尾括起来时
  • 使用lookbehind/lookahead 组合和您的自定义字符类/括号表达式构建您自己的,甚至更复杂的模式。

first two approaches in R 示例(替换为 &lt;&lt;&gt;&gt; 括起来的匹配项):

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."

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多