【问题标题】:How can I capture CLI tool file output to R object or stdout?如何将 CLI 工具文件输出捕获到 R 对象或标准输出?
【发布时间】:2017-07-26 09:20:38
【问题描述】:

我正在从 R 脚本调用一堆命令行界面 (CLI) 工具(例如 texi2pdfpdf2svg,我想捕获输出文件这些工具中的直接作为 R 对象,不接触文件系统

这是更频繁的“how-do-I-redirect-stdout-to-file”问题的相反问题。 (也许这意味着我“用错了”)。

示例

说,我有一个简单的乳胶reprex.tex 文件,我想编译:

\documentclass{article}

\begin{document}

Foo.


\end{document}

在 R 中,我可以使用 tools::texi2pdf() 包装器,或者我可以自己发送命令将其编译为 pdf。

在外壳上,简单地说:

texi2pdf reprex.tex

等效地,从 R 中调用:

reprex_as_pdf <- system2(command = "texi2pdf", args = c(reprex.tex), stdout = TRUE, stderr = TRUE)

很方便,system2() 允许我通过 stdout = TRUE 将 stdout/stderr 捕获为字符向量,这让我成功了一半。

但是,我似乎在texi2pdf manpage 中找不到任何可以让我将(二进制!)输出重定向到stdout(这样,重定向到system2())的内容。

如何在 R 中将texi2pdf 直接 的输出捕获为(原始)向量?

(奖励:我怎样才能将 input 作为 R 字符向量而不是文件传递给 texi2pdf?)


解决方法

我当然可以通过tempfile() 工作,但是触及文件系统,而且看起来不优雅/麻烦。

library(readr)
system2(command = "texi2pdf",
        args = c("reprex.tex"),
        stdout = TRUE,
        stderr = TRUE)
reprex_as_pdf <- read_file_raw("reprex.pdf")

为什么有人愿意这样做?

我通常害怕副作用和跨机器/操作系统文件系统的恶作剧,并希望将副作用隔离到极少数功能。 此外,pdf 实际上将以编程方式导出,转换为各种不同的功能。 最后,我需要 很多 个这些 pdf,我希望它们在部署到可能没有 texi2dvi 的服务器之前轻松编译和缓存。

如果我绝对“用错了”,请阻止我。

【问题讨论】:

  • this question 相关,但与this question 不重复,我想在不接触文件系统的情况下直接捕获knitr::knit() 的输出。 knit() 虽然是原生 R,所以这是一个不同的问题。
  • 在 python 中,您可以将字符串缓冲区附加到进程的标准输出:docs.python.org/2/library/stringio.html。我不了解 R。另外请注意,在 Linux 上写入 /tmp 时,您通常不会点击磁盘(参见 en.wikipedia.org/wiki/Tmpfs#cite_note-4)。内容完全保留在 RAM 中。因此性能可以相当不错,虽然我同意这很麻烦。
  • 我想我在某个时候必须学习 Python ????

标签: r pipe latex command-line-interface system


【解决方案1】:

简单地说:在一般情况下你不能。但有时这些工具允许您指定输出文件,在这种情况下,您可以(在某些系统上,但请注意这是不可移植)指定/dev/stdout 作为输出文件。

根据texi2pdf 联机帮助页,因此以下内容应该有效:

reprex_as_pdf <- system2(
    command = "texi2pdf",
    args = c("reprex.tex", "-o", "/dev/stdout"),
    stdout = TRUE, stderr = TRUE
)

但是,这并不妨碍该工具以其他方式接触文件系统(创建临时文件等)。没有办法阻止这种情况,也不是可取的:这些效果应该对用户透明。一个例外是生成多个输出文件(例如日志文件),不幸的是,TeX 相关工具经常这样做。

回答您的额外问题:这再次以独立于平台的方式是不可能的,但在 POSIX 系统上,您可以创建named pipe。但是,从 R 的角度来看,它的行为与普通文件一样,并且由文件系统管理。

【讨论】:

  • 哦,我忘了:对于输入文件,类似地,您可以使用/dev/stdin。但是,如果该工具除了读取输入文件之外还尝试从标准输入读取命令,这可能会以奇怪的方式中断。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 2010-10-29
  • 2018-04-01
  • 2021-05-21
  • 1970-01-01
相关资源
最近更新 更多