【问题标题】:knitr: generating UTF-8 output from chunksknitr:从块中生成 UTF-8 输出
【发布时间】:2017-10-11 16:52:21
【问题描述】:

我有一个 doc.Rnw 应该产生一些俄罗斯 UTF-8 字符串:

\documentclass{article}
\usepackage{inputenc}
\inputencoding{utf8}
\usepackage[main=english,russian]{babel}
\begin{document}
\selectlanguage {russian} 
<<test, results='asis', echo=FALSE>>=
print(readLines('string.rus', encoding="UTF-8"))

print("Здравствуйте")
@

Здравствуйте
\selectlanguage {english}
\end{document}

string.rus 有一个 UTF-8 字符串,它在 R 控制台中正确显示:

print(readLines('string.rus', encoding="UTF-8"))    
# [1] "Здравствуйте"

doc.Rnw 直接显示在 Windows 记事本中,而两者:

file.show("doc.Rnw")
file.show("doc.Rnw", encoding="UTF-8")

无法正确显示 UTF-8 字符串。

使用:

knit("doc.Rnw")

输出doc.tex的文档部分显示:

\begin{document}
\selectlanguage {russian} 
[1] "<U+0417><U+0434><U+0440><U+0430><U+0432><U+0441><U+0442><U+0432><U+0443><U+0439><U+0442><U+0435>"
[1] " <U+0097>д <U+0080>авс <U+0082>в <U+0083>й <U+0082>е"


Здравствуйте
\selectlanguage {english}
\end{document}

这当然不能在 PDFLaTeX 中编译。使用:

knit("doc.Rnw", encoding="UTF-8")

会产生更糟糕的结果。

注释应该生成 UTF-8 字符串的块:

print(readLines('string.rus', encoding="UTF-8"))     
print("Здравствуйте")

给出一个有效的doc.tex,它在 MikTeX 中编译并正确显示剩余的 UTF-8 字符串。
即使我评论第一个 print... 并只留下第二个。我无法编译。这似乎证明doc.Rnw的原始编码是正确的。

我尝试将两个print 命令替换为:

a="Здравствуйте"
Encoding(a)="UTF-8"
print(a)

在这种情况下我可以编译,但 PDF 输出是(第一个字符串从边距中剪掉):

[1] «U+0417><U+0434><U+0440><U+0430><U+0432><U+0441><U+0442><U+0432><U+0443>
Здравствуйте

所以块输出仍然是错误的。

如何从块中正确打印 UTF-8 字符串?
R 版本是 Windows 的 3.3.3 (2017-03-06),knitr 是 1.15.1 (2016-11-22)。

【问题讨论】:

    标签: r encoding utf-8 knitr


    【解决方案1】:

    一个扩展的工作示例如下:

    \documentclass{article}
    \usepackage{inputenc}
    \inputencoding{utf8}
    \usepackage[main=english,russian]{babel}
    \begin{document}
    \selectlanguage {russian} 
    <<test, results='asis', echo=FALSE>>=
    
    s=readLines('string.rus', , encoding="UTF-8")
    message("s ", Encoding(s), ": ", s)
    Encoding(s)="latin1"
    message("s latin1: ", s)
    Encoding(s)="unkwnown"
    message("s unkwnown: ", s)
    Encoding(s)="utf8"
    message("s utf8: ", a)
    
    
    a="Здравствуйте"
    message("a ", Encoding(a), ": ", a)
    Encoding(a)="latin1"
    message("a latin1: ", a)
    Encoding(a)="utf8"
    message("a utf8: ", a)
    Encoding(a)="UTF-8"
    message("a UTF-8: ", a)
    
    u=("\U0417")
    message("u ", Encoding(u), ": ", u)
    Encoding(u)="latin1"
    message("u latin1: ", u)
    Encoding(u)="unkwnown"
    message("u unkwnown: ", u)
    
    @
    
    Здравствуйте
    \selectlanguage {english}
    \end{document}
    

    knit("doc.Rnw" 之后,这是与doc.tex 中的test 块相关的输出(为了便于阅读,没有进行knitr 代码装饰):

    s UTF-8: <U+0417><U+0434><U+0440><U+0430><U+0432><U+0441><U+0442><U+0432><U+0443><U+0439><U+0442><U+0435>
    
    s latin1: Здравствуйте
    
    s unkwnown: Здравствуйте
    
    s utf8: <U+0417><U+0434><U+0440><U+0430><U+0432><U+0441><U+0442><U+0432><U+0443><U+0439><U+0442><U+0435>
    
    a unknown: Здравствуйте
    
    a latin1: Здравствуйте
    
    a utf8: Здравствуйте
    
    a UTF-8: <U+0417><U+0434><U+0440><U+0430><U+0432><U+0441><U+0442><U+0432><U+0443><U+0439><U+0442><U+0435>
    
    u UTF-8: <U+0417>
    
    u latin1: З
    
    u unkwnown: З
    

    一些 cmets 紧随其后。

    首先,只有message() 有效,print() 总是出错。

    在外部读取的字符串s 和本地设置的a 中,行为都是奇怪
    事实上,将代码保留或显式设置为 UTF-8 会产生错误的结果(utf8 适用于 a)。
    有人可能会认为文档(doc.Rnwstring.rus)的 UTF8 编码设置不正确。这就是为什么我添加了u=("\U0417") 行,它肯定是UTF8。同样,只有删除 UTF8 编码才能提供正确的输出。

    以类似的方式,明确请求 UTF8 输出:

    knit("doc.Rnw", encoding="UTF-8")
    

    不产生 UTF8 字符,但它们的 unicode 值或奇怪的值。

    最后,我可以生成所需的.tex 文件并编译LaTeX,但为什么会出现上述违反直觉的行为是我无法理解的。
    希望有人能给出一个很好的解释。

    【讨论】:

    • 这应该是问题的答案还是编辑?
    • @CL.:既然它是一个可行的解决方案,它就是一个答案。但我不确定这是解决问题的最佳方法,即使是,我也不明白为什么它会以如此不自然的方式工作。还应注意message 适用于字符串,但无法从 xtable 打印表格。
    • 这需要一个凹凸。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-10
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-26
    相关资源
    最近更新 更多