正则表达式,用于在函数体中查找函数调用

Ric*_*ven 0 regex grep r

请将正文read.table视为文本文件,使用以下代码创建:

sink("readTable.txt")
body(read.table)
sink()
Run Code Online (Sandbox Code Playgroud)

使用正则表达式,我想找到表单的所有函数调用foo(a, b, c)(但有任意数量的参数)"readTable.txt".也就是说,我希望结果包含所有被调用函数的名称read.table.这包括表单的嵌套函数
foo(a, bar(b, c)).保留字(return,for使用反单引号(等)和功能'=='(),'+'()可以包含等),因为我可以在以后删除它们.

所以一般来说,我正在寻找模式text(或者text (可能的嵌套函数text1(text2(,但如果它是一个参数而不是函数,跳过文本.这是我到目前为止的地方.它很接近,但并不完全存在.

x <- readLines("readTable.txt")
regx <- "^(([[:print:]]*)\\(+.*\\))"
mat <- regexpr(regx, x)
lines <- regmatches(x, mat)
fns <- gsub(".*( |(=|(<-)))", "", lines)
head(fns, 10)
# [1] "default.stringsAsFactors()" "!missing(text))"
# [3] "\"UTF-8\")" "on.exit(close(file))" "(is.character(file))"
# [6] "(nzchar(fileEncoding))" "fileEncoding)" "\"rt\")"
# [9] "on.exit(close(file))" "\"connection\"))"
Run Code Online (Sandbox Code Playgroud)

例如,在[9]上面,调用是存在的,但我不想file在结果中.理想情况下会是这样on.exit(close(.

我怎样才能改进这个正则表达式?

MrF*_*ick 6

如果您曾尝试使用正则表达式解析HTML,那么您知道它可能是一场噩梦.使用一些HTML解析器并以这种方式提取信息总是更好.我对R代码有同感.R的优点在于它的功能性,您可以通过代码检查任何功能.

就像是

call.ignore <-c("[[", "[", "&","&&","|","||","==","!=",
    "-","+", "*","/", "!", ">","<", ":")

find.funcs <- function(f, descend=FALSE) {
    if( is.function(f)) {
        return(find.funcs(body(f), descend=descend))
    } else if (is(f, "name") | is.atomic(f)) {
        return(character(0))
    }
    v <- list()
    if (is(f, "call") && !(deparse(f[[1]]) %in% call.ignore)) {
        v[[1]] <- deparse(f)
        if(!descend) return(v[[1]])
    } 
    v <- append(v, lapply(as.list(f), find.funcs, descend=descend))
    unname(do.call(c, v))
}
Run Code Online (Sandbox Code Playgroud)

可以工作.在这里,我们迭代函数中的每个对象寻找calls,忽略那些你不关心的对象.你可以在像这样的函数上运行它

find.funcs(read.table)

# [1] "default.stringsAsFactors()"                
# [2] "missing(file)"                             
# [3] "missing(text)"                             
# [4] "textConnection(text, encoding = \"UTF-8\")"
# [5] "on.exit(close(file))"                      
# [6] "is.character(file)"  
# ...
Run Code Online (Sandbox Code Playgroud)

如果要查看其他函数的函数调用,可以将descend=参数设置TRUE为.

我确信有很多软件包可以让这更容易,但我只是想表明它是多么简单.