如何捕获系统的输出()

时间:2022-11-21 13:56:12

This question was motivated by Rmarkdown not outputting results of system command to html file. For some reason, the output of system() in R (or system2()) cannot be captured by sink() or capture.output(), so currently there is no way for knitr to record the output. For example, in the R console:

这个问题的动机是Rmarkdown没有将系统命令的结果输出到html文件。由于某种原因,sink()或capture.output()无法捕获R(或system2())中system()的输出,因此目前knitr无法记录输出。例如,在R控制台中:

> system('ls')
DESCRIPTION
NAMESPACE
R
README.md
inst
man

but in a knitr document, you won't see the output, because capture.output(system('ls')) is character(0), i.e. the output cannot be captured. Of course I can do cat(system('ls', intern = TRUE), sep = '\n') as I mentioned in the answer of that question, but this is kind of awkward. I wonder if it is a way to capture the output of system() without using intern = TRUE and cat().

但在knitr文档中,您将看不到输出,因为capture.output(system('ls'))是字符(0),即无法捕获输出。当然我可以做cat(系统('ls',实习生= TRUE),sep ='\ n'),就像我在那个问题的答案中提到的那样,但这有点尴尬。我想知道它是否是一种捕获system()输出的方法,而不使用intern = TRUE和cat()。


Update: see https://github.com/yihui/knitr/issues/1203 for a hack that I provided to solve the problem.

更新:请参阅https://github.com/yihui/knitr/issues/1203,了解我为解决问题而提供的黑客攻击。

2 个解决方案

#1


4  

You could add a function knitr::system that masks base::system. Users could work with it like it was system::base, but the output can be captured by capture.output:

你可以添加一个函数knitr :: system来掩盖base :: system。用户可以像使用system :: base一样使用它,但是可以通过capture.output捕获输出:

system <- function(...) {
  stopifnot(!any(names(list(...)) %in% "intern"))
  result <- base::system(..., intern = TRUE)
  print(result)
}

I admit, that this is somewhat hacky, and to be honest, I'm not sure about possible side effects. But I think it could be worth a try.

我承认,这有些愚蠢,说实话,我不确定可能的副作用。但我认为值得一试。

#2


5  

I don't think you can do this (at least on *nix systems; I don't have a Windows/Mac system handy) because system appears to invisibly return the value returned by the command executed, and R doesn't appear to redirect the command's output to the R console.

我不认为你能做到这一点(至少在* nix系统上;我没有Windows / Mac系统),因为系统似乎无形地返回执行命令返回的值,而R似乎没有将命令的输出重定向到R控制台。

This is because the stdout of your terminal is not the same as the R console "stdout". What you see from within your R session is the mix of the terminal's stdout and the R process output. capture.output is looking for the R process' output, not all output to stdout from the parent process.

这是因为终端的标准输出与R控制台“标准输出”不同。你在R会话中看到的是终端的stdout和R进程输出的混合。 capture.output正在寻找R进程的输出,而不是从父进程到stdout的所有输出。

You can start a process that prints to stdout, put it in the background, then start R... and you'll see that process' output in your "R output", similar to if you had run system("ping -c5 8.8.8.8") from R.

您可以启动一个打印到stdout的进程,将其放在后台,然后启动R ...然后您将在“R输出”中看到该进程的输出,类似于您运行系统(“ping -c5”来自R.的8.8.8.8“)

josh@computer: /home/josh
> ping -c5 8.8.8.8 & R
[1] 5808
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=46 time=39.9 ms

R version 3.2.4 Revised (2016-03-16 r70336) -- "Very Secure Dishes"
Copyright (C) 2016 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

> 64 bytes from 8.8.8.8: icmp_seq=2 ttl=46 time=38.1 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=46 time=38.3 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=46 time=38.4 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=46 time=38.3 ms

--- 8.8.8.8 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4003ms
rtt min/avg/max/mdev = 38.176/38.656/39.986/0.703 ms

> q()
Save workspace image? [y/n/c]: n
[1]+  Done                    ping -c5 8.8.8.8

josh@computer: /home/josh
> 

#1


4  

You could add a function knitr::system that masks base::system. Users could work with it like it was system::base, but the output can be captured by capture.output:

你可以添加一个函数knitr :: system来掩盖base :: system。用户可以像使用system :: base一样使用它,但是可以通过capture.output捕获输出:

system <- function(...) {
  stopifnot(!any(names(list(...)) %in% "intern"))
  result <- base::system(..., intern = TRUE)
  print(result)
}

I admit, that this is somewhat hacky, and to be honest, I'm not sure about possible side effects. But I think it could be worth a try.

我承认,这有些愚蠢,说实话,我不确定可能的副作用。但我认为值得一试。

#2


5  

I don't think you can do this (at least on *nix systems; I don't have a Windows/Mac system handy) because system appears to invisibly return the value returned by the command executed, and R doesn't appear to redirect the command's output to the R console.

我不认为你能做到这一点(至少在* nix系统上;我没有Windows / Mac系统),因为系统似乎无形地返回执行命令返回的值,而R似乎没有将命令的输出重定向到R控制台。

This is because the stdout of your terminal is not the same as the R console "stdout". What you see from within your R session is the mix of the terminal's stdout and the R process output. capture.output is looking for the R process' output, not all output to stdout from the parent process.

这是因为终端的标准输出与R控制台“标准输出”不同。你在R会话中看到的是终端的stdout和R进程输出的混合。 capture.output正在寻找R进程的输出,而不是从父进程到stdout的所有输出。

You can start a process that prints to stdout, put it in the background, then start R... and you'll see that process' output in your "R output", similar to if you had run system("ping -c5 8.8.8.8") from R.

您可以启动一个打印到stdout的进程,将其放在后台,然后启动R ...然后您将在“R输出”中看到该进程的输出,类似于您运行系统(“ping -c5”来自R.的8.8.8.8“)

josh@computer: /home/josh
> ping -c5 8.8.8.8 & R
[1] 5808
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=46 time=39.9 ms

R version 3.2.4 Revised (2016-03-16 r70336) -- "Very Secure Dishes"
Copyright (C) 2016 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

> 64 bytes from 8.8.8.8: icmp_seq=2 ttl=46 time=38.1 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=46 time=38.3 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=46 time=38.4 ms
64 bytes from 8.8.8.8: icmp_seq=5 ttl=46 time=38.3 ms

--- 8.8.8.8 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4003ms
rtt min/avg/max/mdev = 38.176/38.656/39.986/0.703 ms

> q()
Save workspace image? [y/n/c]: n
[1]+  Done                    ping -c5 8.8.8.8

josh@computer: /home/josh
>