如何在R中提取脚本内函数定义的行号、标题等信息?
问题描述
我有一段保存为function.R的R代码,内容如下:
#' This function is cool #' #' blablabla..... #' @export #' @param hello a parameter of my function f_cool <- function(hello) { # some code # some other code }
请问是否有办法以列表形式按行号提取函数定义的大纲信息?例如调用类似map_fn_definition("function.R")的函数后,能返回如下结果:
#> $f_cool #> $f_cool$line_start #> 6 #> $f_cool$line_end #> 9 #> $f_cool$title #> "This function is cool"
我了解roxygen2可能实现该功能,但该工具的文档侧重生成包的.Rd文件,因此特向您寻求解决方案。
解决方案
可以通过解析文件文本内容,结合正则匹配与语法逻辑判断实现需求,以下是自定义的map_fn_definition函数:
map_fn_definition <- function(file_path) { # 读取文件所有行 lines <- readLines(file_path) line_count <- length(lines) # 匹配函数定义行(格式:函数名 <- function(...)) fn_def_pattern <- "^\\s*([a-zA-Z0-9._]+)\\s*<-\\s*function\\s*\\(" fn_def_matches <- regexec(fn_def_pattern, lines) fn_positions <- which(sapply(fn_def_matches, function(x) x[1] != -1)) result <- list() for (pos in fn_positions) { # 提取函数名 fn_name <- regmatches(lines[pos], fn_def_matches[[pos]])[2] # 定位函数结束行:统计大括号数量,处理嵌套情况 brace_count <- 0 end_line <- line_count for (i in pos:line_count) { current_line <- lines[i] brace_count <- brace_count + stringr::str_count(current_line, "\\{") - stringr::str_count(current_line, "\\}") if (brace_count == 0 && i > pos) { end_line <- i break } } # 提取roxygen标题:向上查找第一个有效注释行 title <- NA_character_ for (i in (pos-1):1) { current_line <- lines[i] if (grepl("^#'\\s+", current_line)) { title <- gsub("^#'\\s+", "", current_line) break } else if (trimws(current_line) != "") { # 遇到非roxygen注释内容,停止查找 break } } # 存入结果列表 result[[fn_name]] <- list( line_start = pos, line_end = end_line, title = title ) } return(result) }
函数逻辑说明
- 定位函数起始行:通过正则匹配找到所有符合
函数名 <- function(...)格式的行; - 确定函数结束行:遍历行号统计大括号的开闭数量,确保找到函数定义对应的闭合大括号(支持嵌套大括号场景);
- 提取roxygen标题:从函数起始行向上遍历,找到第一个以
#'开头的非空注释行,作为函数标题; - 返回结果:将每个函数的起始行号、结束行号、标题信息整理为列表返回。
使用示例
调用函数前需先安装并加载stringr包:
install.packages("stringr") library(stringr)
执行map_fn_definition("function.R"),会返回符合需求的结果:
#> $f_cool #> $f_cool$line_start #> [1] 6 #> #> $f_cool$line_end #> [1] 9 #> #> $f_cool$title #> [1] "This function is cool"
内容的提问来源于stack exchange,提问作者olivroy
相关产品推荐
相关产品推荐

