2016-04-29 89 views
16

這個問題的動機是Rmarkdown not outputting results of system command to html file。出於某種原因,R(或system2())中的system()的輸出不能被sink()capture.output()捕獲,因此目前沒有辦法記錄輸出。例如,在R控制檯:如何捕獲系統的輸出()

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

但在一個knitr文件,就不會看到輸出,因爲capture.output(system('ls'))character(0),即輸出不能被捕獲。正如我在這個問題的答案中提到的那樣,我當然可以做cat(system('ls', intern = TRUE), sep = '\n'),但這有點尷尬。我想知道是不是使用intern = TRUEcat()來捕獲system()的輸出。


更新:看到https://github.com/yihui/knitr/issues/1203爲我提供瞭解決問題的一個黑客。

回答

4

你可以添加一個功能knitr::system掩蓋base::system。用戶可以使用它就像是system::base,但輸出可以通過capture.output捕獲:

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

我承認,這是有點哈克,而且說實話,我不知道關於可能的副作用。但我認爲這可能值得一試。

+0

謝謝!我意識到這一點,但如果我能找到一種方法來捕獲'system()'的輸出,我就不會使用它。在Joshua Ulrich的回答下看到我的評論。 –

+0

@Yihui它不是*那*壞 - 特別是知道例如'system'中的'ignore.stdout'和'ignore.stderr'選項只需添加'>/dev/null'或'2>/dev/null'重定向到'command' :) – daroczig

5

我不認爲你可以做到這一點(至少在* nix系統上;我沒有Windows/Mac系統的便利),因爲system似乎無形地返回了執行命令返回的值,而R doesn似乎不會將命令的輸出重定向到R控制檯。

這是因爲您的終端的stdout與R控制檯「stdout」不一樣。你在R會話中看到的是終端的stdout和R處理輸出的混合。 capture.output正在尋找R進程的輸出,而不是所有從父進程輸出到stdout

你可以啓動一個打印到stdout的進程,把它放在後臺,然後啓動R ...,你會在你的「R輸出」中看到該進程的輸出,類似於你運行從system("ping -c5 8.8.8.8") R.

[email protected]: /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 

[email protected]: /home/josh 
> 
+1

我不認爲無形的返回值是問題。我期望'capture.output()'捕獲stdout,儘管這不是記錄的內容(文檔使用了一個模糊的單詞「output」,我不知道它是否意味着stdout)。例如,你可以''capture.output((函數(){print(「Hello world!」); invisible(「hi」)})())'並且它從'print()'中捕獲'Hello world! 。我的實際問題是爲什麼可以捕獲'print()'的輸出,但'system()'的輸出不能。它可以是'system()'不寫入標準輸出,或'capture.output()'並不真正捕獲標準輸出。 –

+0

@Yihui不是說我是R內部專家,但[this](https://github.com/wch/r-source/blob/e5b21d0397c607883ff25cca379687b86933d730/src/unix/sys-unix.c#L337)line _does_似乎建議'system'使用'stdout'(與我的預期相反) – MichaelChirico

+0

@MichaelChirico感謝您挖掘C代碼。然後我猜我的下一個問題是'capture.output()'真的捕獲了什麼樣的輸出。 –