Rコマンドそのものをフィルタとして使う勝手はよくないようだ。 パイプの先でRを使うより、処理すべきものを引数リストで渡して Rで能動的に処理させた方がやりやすい感じ。
最初、標準入力を取らせようと思って
scan("", what=list(a="", b=0))
みたいにして、Rscript hoge.R < file したけどだめだった。
scan のファイル名に /dev/stdin
もだめ。
NetBSDはうまくいくけどSolarisでNG。
Rで ?connections
したらだいたい分かった。なるほど。
標準入力を取らせたいなら
fd <- pipe("cat") scan(file=fd, ...) close(fd)
みたいな感じでOK。外部コマンドを読んで結果をとるならpipe() でよい感じ。これを使おう。
ということでシェルスクリプトでループしてその内部で Rへパイプで標準入力渡しより、先に複数の引数を渡してRでループさせた 方が楽。
コマンドライン引数は commandArgs()
で取れて、
commandArgs(T)
で --args
より後ろのもの(つまり欲しいものだけ)取り出せる。
$DISPLAY がセットされてないと、というかX11()環境がないと PNGもJPEGも吐き出せないとな! バックグラウンド動作させられないじゃないか! RjpWiki R-FAQ 7.21 か。Xvfb を使えとあるが、うちの Solaris10/sparc でうまく行かなかった。けどまあ、どっか自由に使えるDISPLAYがあれば いいってことで、幸いXvncを導入済みなのでそれを使った。
Xvnc :xxxx export DISPLAY=:xxxx
行けた。でも起動しとくことを忘れそうだな。
シェルスクリプト屋の頭でこんな感じのことをやろうとしていた。
for i in "$@"; do grep hoge $i/* | sort | uniq -c | Rscript hogehoge.R done
Rで標準入力を受けて文字列処理をごにょごにょやるのもなんだし、 R自体の起動も重いので次のように変えた。
DISPLAY=:xxxx Rscript hogehoge2.R "$@"
でhogehoge2.R
はこんな風。
#!/usr/bin/env Rscript for (i in commandArgs(T)) { png(file=sprintf("output/%i.png", i)) fd=pipe(sprintf("grep hoge %s/* | sort | uniq -c")) x <- scan(file=fd, what=list(count=0, item="")) close(fd) # グラフ作成いろいろ dev.off() done