Quarto中如何用system(kpsewhich(...))查找参考文献文件?
之前在R Markdown中,我们可以在YAML的bibliography字段里通过`r system('kpsewhich xxx.bib', intern=TRUE)`的方式,直接引用系统级localtexmf文件夹中的.bib文件,无需复制到项目目录或写死绝对路径。但这套方案在Quarto中完全失效:
原R Markdown中的可行配置:
bibliography: - references.bib - "`r system('kpsewhich graphics.bib', intern=TRUE)`" - "`r system('kpsewhich statistics.bib', intern=TRUE)`" - "`r system('kpsewhich timeref.bib', intern=TRUE)`"
在Quarto中使用时会报错:
Preparing to preview [1/2] intro.qmd File r system('kpsewhich graphics.bib', intern=TRUE) not found in resource path
但直接在R控制台执行system('kpsewhich graphics.bib', intern=TRUE)能正常返回文件路径。
后续测试还发现:Quarto不支持在YAML中用`r ...`嵌入R代码(比如设置date字段时会显示"Invalid date"),改用!expr语法能解决日期字段的问题,但在bibliography字段中使用时,若system()调用拆分行写,会出现解析错误:
bibliography: - references.bib - tag: '!expr' value: system('kpsewhich graphics.bib' - intern=TRUE) # 报错提示:File intern=TRUE) not found in resource path
1. 正确使用!expr语法(避免换行拆分)
Quarto要求YAML中的R表达式必须通过!expr前缀标记,且整个表达式必须写在同一行,不能拆分。正确的配置如下:
bibliography: - references.bib - !expr system('kpsewhich graphics.bib', intern=TRUE) - !expr system('kpsewhich statistics.bib', intern=TRUE) - !expr system('kpsewhich timeref.bib', intern=TRUE)
这样Quarto会正确解析每个!expr后的R代码,执行后获取对应的.bib文件路径。
2. 更可靠的替代:用tinytex::kpsewhich()
推荐直接使用tinytex包提供的kpsewhich()函数,它无需调用系统命令,直接返回文件路径,写法更简洁,也能避免系统命令调用的解析问题:
# 确保已安装tinytex包:install.packages("tinytex") bibliography: - references.bib - !expr tinytex::kpsewhich("graphics.bib") - !expr tinytex::kpsewhich("statistics.bib") - !expr tinytex::kpsewhich("timeref.bib")
3. 全局配置(可选)
如果需要在多个Quarto项目中复用这些系统级bib路径,可以在用户级Quarto配置文件(~/.quarto/config.yml)中添加全局bibliography配置:
bibliography: - !expr tinytex::kpsewhich("graphics.bib") - !expr tinytex::kpsewhich("statistics.bib") - !expr tinytex::kpsewhich("timeref.bib")
之后在项目的YAML中只需添加项目本地的references.bib即可:
bibliography: - references.bib
Quarto与R Markdown在YAML解析R代码的机制不同:
- R Markdown支持在YAML字符串中用
`r ...`嵌入R代码,渲染时会自动执行替换; - Quarto不支持这种写法,必须用
!expr前缀标记YAML中的R表达式,且要求表达式结构完整(不能换行拆分,否则会被解析为多个列表项)。
内容的提问来源于stack exchange,提问作者user101089

