动态生成section时read_metainfo读取含Sexpr的.Rnw文件报错问题
read_metainfo()读取含\Sexpr的\exsolution时出错/报警告 问题描述
我想通过exams2moodle()的stitle参数动态生成section,不用.Rnw文件里的\exsection,要求stitle结合目录结构和.Rnw中的exname值。但用read_metainfo()读取exname时,只要.Rnw的\exsolution里包含\Sexpr就会报错;更新exams包后虽然程序不会终止,但仍会弹出警告。
附foo.Rnw内容:
<<echo=FALSE, results=hide>>= solution <- 10 @ \exname{foo} \exsection{bar} \extype{num} \exsolution{\Sexpr{solution}} \begin{question} Foo text... \end{question}
原因分析
read_metainfo()解析\exsolution时,默认会调用string2num()尝试把内容转成数值,但\Sexpr{solution}是未编译的R表达式占位符,没法直接转成有效数值,所以触发了类型转换错误/警告。更新包后程序不终止,说明官方优化了错误处理逻辑,但警告还是会存在。
解决方法
方法1:关闭元信息自动解析(快速规避警告)
调用read_metainfo()时加parse = FALSE参数,跳过对元信息的自动解析,这样就不会尝试转换exsolution为数值,能正常读取exname:
meta <- read_metainfo("foo.Rnw", parse = FALSE) exname_val <- meta$exname
拿到exname_val后,就可以结合目录结构生成stitle,再传入exams2moodle()。
方法2:预编译.Rnw后读取元信息
先用knit()编译.Rnw生成临时.tex文件,此时\Sexpr{solution}会被替换成实际数值,再读取编译后的文件元信息就不会有转换问题:
library(knitr) knit("foo.Rnw", output = "foo_temp.tex") meta <- read_metainfo("foo_temp.tex") exname_val <- meta$exname # 用完临时文件可删除 file.remove("foo_temp.tex")
方法3:正则直接提取exname(轻量方案)
如果只需要exname,可以直接读.Rnw文本,用正则表达式匹配提取,完全绕开read_metainfo()的解析逻辑:
rnw_content <- readLines("foo.Rnw") exname_match <- grep("\\\\exname\\{(.*)\\}", rnw_content, value = TRUE) exname_val <- sub("\\\\exname\\{(.*)\\}", "\\1", exname_match)
补充说明
更新exams包后程序不再终止,说明致命错误已被修复,但转换警告还会存在,上面的三种方法都能消除警告并顺利拿到exname。
内容的提问来源于stack exchange,提问作者uzsolt

