[R] Rの標準入出力

2018年3月26日月曜日

R

Rで他のスクリプトと連携できないかと思って、標準入力から読み込んで、標準出力に加工後のデータを出力するスクリプトを作ろうとしたら、変なところではまってしまった。

まずはこれ

最終的にはこうなった。

inout.R
data <- read.csv("stdin")
#何か処理...
write.csv(data, stdout(), row.names = FALSE)
これを以下のように実行すると標準入力からCSV区切りのテキストを読んで、標準出力に出してくれる。

$ Rscript --slave --vanilla inout.R

でもさ

さっきのスクリプトをよく見ると、入力は"stdin"という文字列なのに、出力はstdout()という関数呼び出しになっている。
試しに出力側を"stdout"という文字列にしてみると
write.csv(data, "stdout", row.names = FALSE)
この場合はstdoutという名前のファイルに出力されてしまう。

Rの標準入力はどこから来るのか

じゃあ、入力側をstdin()にしてみるとどうなるか。
data <- read.csv(stdin())
にすると、何も出力されない。。。

https://stat.ethz.ch/R-manual/R-devel/library/base/html/showConnections.html
のNoteを見ると
stdin() refers to the ‘console’ and not to the C-level ‘stdin’ of the process. The distinction matters in GUI consoles (which may not have an active ‘stdin’, and if they do it may not be connected to console input), and also in embedded applications. If you want access to the C-level file stream ‘stdin’, use file("stdin").

When R is reading a script from a file, the file is the ‘console’: this is traditional usage to allow in-line data (see ‘An Introduction to R’ for an example).

うーん、どうやらスクリプトファイルから処理を実行しているときはファイル自体がconsoleと見なされるみたい。
で、インラインデータというのはヒアドキュメントみたいに、その場にデータを書くものらしい。

stdinout.R
data <- read.csv(stdin())
apple,orange,grape
1,2,3
4,5,6

write.csv(data, stdout(), row.names = FALSE)

こんな感じでstdin()を書いた直後からインラインデータが始まり、空行までデータが続く。
実行すると、CSVヘッダとデータが出力されるのがわかる。
$ Rscript --slave --vanilla stdinout.R
"apple","orange","grape"
1,2,3
4,5,6