问题描述

我昨天把电脑中安装的R包全部更新到最新后,发现使用bookdown总是出现编译失败,而在R包升级之前是没有出现的。初步判断,应该是.Rmd文件中的标题使用了中文,因为标题全部改为英文后就能正常编译;但是少量中文又能编译成功。不知道哪里出现问题了,我该怎样修正这个问题。还请大佬指教(能召唤益辉大哥吗?@yihui),不胜感激!

index.Rmd文件内容

--- 
title: "A Minimal Book Example"
author: "LHX"
date: "`r Sys.Date()`"
site: bookdown::bookdown_site
output: bookdown::gitbook
documentclass: book
bibliography: [book.bib, packages.bib]
biblio-style: apalike
link-citations: yes
description: ""
---

# 总体介绍{-}

# 三国人物

## 魏国

### 曹操

东汉丞相。

## 蜀国

# 唐宋名将

编译失败提示结果



processing file: bookdown-demo.Rmd
  |.................................................................| 100%
   inline R code fragments


output file: bookdown-demo.knit.md

"E:/EngSoft/R/RStudio/bin/pandoc/pandoc" +RTS -K512m -RTS bookdown-demo.utf8.md --to html4 --from markdown+autolink_bare_uris+tex_math_single_backslash+smart --output bookdown-demo.html --email-obfuscation none --wrap preserve --standalone --section-divs --table-of-contents --toc-depth 3 --template "E:\EngSoft\R\library\bookdown\templates\gitbook.html" --highlight-style pygments --number-sections --css style.css --include-in-header "C:\Users\Administrator\AppData\Local\Temp\RtmpqgKzLU\rmarkdown-str22dc11395c39.html" --mathjax --lua-filter "E:/EngSoft/R/library/rmarkdown/rmd/lua/pagebreak.lua" --lua-filter "E:/EngSoft/R/library/rmarkdown/rmd/lua/latex-div.lua" --filter "E:/EngSoft/R/RStudio/bin/pandoc/pandoc-citeproc.exe" 
Error in file.exists(f) : 转换文件名时出了问题--名字太长了?
Calls: <Anonymous> ... move_files_html -> local_resources -> grep -> unique -> file.exists
Please delete bookdown-demo.Rmd after you finish debugging the error.
停止执行

_bookdown.yml文件内容

book_filename: "bookdown-demo"
language:
  label:
    fig: "图"
    tab: "表"
  ui:
    edit: "编辑"
    chapter_name: ["第", "章"]
rmd_files: ["index.Rmd"]

我的系统环境

R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

Matrix products: default

locale:
[1] LC_COLLATE=Chinese (Simplified)_People's Republic of China.936 
[2] LC_CTYPE=Chinese (Simplified)_People's Republic of China.936   
[3] LC_MONETARY=Chinese (Simplified)_People's Republic of China.936
[4] LC_NUMERIC=C                                                   
[5] LC_TIME=Chinese (Simplified)_People's Republic of China.936    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] compiler_3.6.1  bookdown_0.14   htmltools_0.4.0 tools_3.6.1     yaml_2.2.0     
 [6] Rcpp_1.0.2      rmarkdown_1.16  knitr_1.25      xfun_0.10       digest_0.6.21  
[11] rlang_0.4.0     evaluate_0.14 

我用的bookdown模板已上传至百度网盘中。

另外,将index.Rmd内容中的## 蜀国改为## 郭嘉又能编译成功,所以我很迷惑。

    dugucan 百度网盘下载个东西还得账号登录,我懒得折腾,所以就没下载。往后可以把 zip 压缩包上传到 Github 的任意事项页面里,比如这个问题最合适的就是在 https://github.com/rstudio/bookdown 的事项页面里报告并上传示例。

    我大概知道怎么解决这个问题,就是在你的中文标题后面附上纯 ASCII 字符的 ID,比如 ## 蜀国 {#shuguo}。但这个 file.exists() 的错误消息我看不懂。因为我没法下载你的例子,所以也没法研究。

    之所以更新了 R 包出现这个问题,应该是跟 rmarkdown 1.16 去掉了以前默认的 Pandoc 扩展 ascii_identifiers 有关。

      yihui 谢谢益辉大佬的答复,应该确实是rmarkdown 1.16去掉了那个扩展的问题,我将## 蜀国改成## 蜀国{#shuguo}后编译成功了。

      现在已经升级到最新版了,不想再回去了。看到github中说可以使用md_extensions = "+ascii_identifiers" 这个参数,但可能会引起Pandoc后续版本的错误,保险起见,后面就在每一个标题后面都手动加上类似{#shuguo}的东西吧。

      再次谢谢益辉大哥!

      赞问题问得眉清目秀,不过一级标题好像太大了!

        tctcab 这两句话我当时看到帖子后本来只是在心里说了一下,现在你帮我打出来了。我已经无限接近要邀请楼主来做版主了。

          tctcab yihui 接受二佬的批评,我已经修改了标题级别,这下看得清爽一点了。 😄

            楼主加入于 2013 年,是前辈啊!欢迎加入版主队伍

              百度网盘的模板在我这里下载了之后编译失败。原因之一是 documentclass: book。换成 documentclass: ctexbook 才行。

              此外,如果中文标题太多,手动给每个标题加 ID 嫌麻烦的话,可以用 pinyin::bookdown2py()函数,自动给 .Rmd 每个标题添加个拼音 ID。
              `

                dapengde
                哇在另一个blogdown的小项目里一直想要这个功能的说!!终于可以优雅地给中文标题的post加上slug了哈哈哈

                  dapengde tctcab 那就告诉你们一个花钱买不到的绝招吧。blogdown 的文件名和短链接(slug)都是可以通过自定义函数生成的,如果要汉字自动转拼音的话,可作如下设置:

                  options(blogdown.filename.pre_processor = function(x) {
                      pinyin::py(x, sep = '-', dic = pinyin::pydic('toneless'))
                  })

                  然后插件 New Post 里敲汉字就会自动出来拼音文件名和短链接:

                  Screen Shot 2019-10-17 at 4 19 11 PM

                  然而 pinyin::py() 有个不太合理的地方,就是把字符串拆成单个字符之后转换,然后再(默认)用下划线拼接起来,如“你好abc”会被转成“ni-hao-a-b-c”,我觉得转成“ni-hao-abc”更合理一些,不过这个实现起来会稍微费劲一点点。另外感觉这函数跑起来略慢,似乎有提速的可能,看哪位壮士有空细究帮忙吧。

                  Cloud2016 已经在 dugucan 头上劈了一道闪电。

                    yihui 这确实是个绝招!我平时创建新的博客都是复制之前的然后替换,因为上面提到的文件名的问题,替换只是举手之劳。英文环境下的写作,这个创建博文的插件应该是完美的!

                      Cloud2016 复制文件、手工替换对我来说是举好几次手之劳:日期要替换两遍(文件名里一遍、日志文件里面日期栏一遍),然后标题要删一遍,短链接要写两遍(仍然是外面里面各一遍,虽然外面不是必需的)。所以我一般都用这个插件创新新日志,只需要敲标题和文件名里的短链接部分,其它事情都是自动的。我的中文日志一般都用英文单词作短链接。

                        yihui

                        有空开始研究了一下这个包,从我的1200+条标题转换记录来0.5秒 看还是挺快的啊

                        但是准确率堪忧…@dapengde 怎么回事

                        pinyin::py("我喜欢旅游", dic= pinyin::pydic("toneless"))
                        #>           我喜欢旅游 
                        #> "wo_chi_huan_lv_liu"
                        pinyin::py("我受不了了",dic= pinyin::pydic("toneless"))
                        #>        我受不了了 
                        #> "wo_dao_bu_le_le"

                        <sup>Created on 2019-10-18 by the reprex package (v0.3.0)</sup>

                          yihui 我的老天,这黑科技太牛了,然而藏得也太深了,搜啊搜只在 blogdown 的 NEWS 里搜到一条:

                          pinyin 包跑起来略慢,原因可能是因为下面这一句,把 py()pydic() 两个函数合成一句的缘故:

                          pinyin::py(x, sep = '-', dic = pinyin::pydic('toneless'))

                          慢在 pydic(),它用来载入字典,然而一劳永逸,载入之后,每次转换时只需执行 py()函数就快了。例如:

                          require(pinyin)
                          mydic <- pydic("toneless")
                          py("我喜欢旅游", dic= mydic)
                          py("我受不了了", dic= mydic)

                          肯定比

                          pinyin::py("我喜欢旅游", dic= pinyin::pydic("toneless"))
                          pinyin::py("我受不了了", dic= pinyin::pydic("toneless"))

                          快很多。

                          历史上,pinyin 经过了一次提速。提速前,用的方法是简单粗暴的文本查找替换。有一天,有个用户要转换大量的汉字,发现这样太慢,就给我提出了两个改进方案:一个是把拼音库转成 environment,另一个是并行计算。我采纳了第一个,所以才有了 pydic() 函数,目的就是把原来的文本拼音库转成 environment。

                          tctcab 准确率堪忧的原因是没有解决多音字的问题。因为现在是逐字在拼音库里找一个字的拼音,它没法根据上下文(字)判断受不了了里的两个的读音区别,所以默认从库里选择第一个。也可以把所有读音都在结果里列出来,但是就是不会智能选择正确的那个。默认拼音库里的多音字很多,有些音从来没见过。可以换个拼音库 (dic = 'pinyin2'),内含常用读音:

                          mydic <- pydic(method = 'toneless', dic = 'pinyin2')
                          py("我喜欢旅游", dic= mydic)
                                   我喜欢旅游 
                          "wo_xi_huan_lv_you" 

                          然而这仍然没解决 我受不了了 的问题。目前只能凑合用了。

                          我看了一下别的软件,好像也没能解决这个问题。例如<http://xh.5156edu.com/conversion.html> 和 <https://zhongwenzhuanpinyin.51240.com/>。

                          Cloud2016
                          a-b-c 这个问题当时我考虑过,一度想挽起袖子给解决了,后来懒兵一犯,得过且过了。

                          pinyin 包是刚学会写包时写的,生涩得很,目的是够用,在不得已的一些场合(例如 bookdown 的中文章节 ID,例如操作系统不支持中文文件名等)里把汉字替换成字母而已。现在回头去看,要改的地方很多,连文档都没好好写,无奈没有那个精力了,可预见的未来也没有时间去改进。哪位好汉有时间的话就接过去吧。

                          对了,它还可以把汉字转换成五笔码和四角号码,例如:

                          dic_wb98 <- 'https://github.com/pzhaonet/pinyin/raw/master/inst2/wubi98.txt'
                          mywb98 <- load_dic(dic_file = dic_wb98)
                          py("春眠不觉晓,处处闻啼鸟", sep = '_', dic = mywb98)

                          也支持用户自定义字典。反正本质就是个批量查找替换。可以开开脑洞,看看它还能做什么。