1 背景
1 background
在bash中使用R脚本是一件很方便的事。通常在R脚本中使用R函数commandArgs()来读取命令后面的参数。但这个R函数无法接收管道传过来的参数,从而限制Rscript的使用。本文旨在让Rscript不仅可以接收命令后面的参数,也可以接收管道里上一个命令传过来的参数。具体情况如下图。
It’s convenient to use R scripts in bash. In R scripts, R function commandArgs() is commonly used to get arguments after the command. But this R function can’t receive arguments passed via pipe. This may restrict the usage of Rscript. This article aims to make Rscript receives not only arguments afterwards, but also arguments passed from the previous command in a pipe. See the picture below for details.
这里的Rscript是指,(1)R脚本,可以在bash中用“Rscript script_name [arguments]”来运行;(2)第一行通常是“#! /usr/bin/Rscript”或“#! /usr/bin/env Rscript”,并且有执行权限的R脚本,可以在bash中用“path/to/script_name [arguments]”来运行。可以使用“chmod +x script_name”为R脚本添加执行权限。如果R脚本就在当前工作文件夹,应当使用“./script_name [arguments]”,而非“script_name [arguments]”;(3)将R脚本放到PATH中的某一个文件夹(如~/.local/bin/)之后,可以像命令一样使用,如“script_name [arguments]”。
Rscript here means, (1) R scripts. Use “Rscript script_name [arguments]” to run it in bash. (2) Executable R scripts whose first line is usually “#! /usr/bin/Rscript” or “#! /usr/bin/env Rscript”. Use “path/to/script_name [arguments]” to run it in bash. You can use “chmod +x script_name” to add executable permission to R scripts. If the R script locates in current working directory, use “./script_name [arguments]” instead of “script_name [arguments]” to run it. (3) After putting them into one of the directories (e.g. ~/.local/bin/) specified in PATH, R scripts can be used like commands, for example “script_name [arguments]”.
2
接收管道传过来的数据可能与stdin有关,而commandArgs()不从stdin中接收数据。根据R手册,R中的stdin有两种,我也搞不清楚这些。与stdin有关的R函数大概有以下几个。
Receiving data passed via pipe may have something related to stdin, while commandArgs() doesn’t receive data from stdin. According to R manuals, there are two kinds of stdin in R. I don’t really understand this. Below are R functions related to stdin in my memory.
# 1 Try stdin(). The 3 codes are same.
readLines(con=stdin())
scan(file=stdin(), what=character())
scan(file="", what=character())
# 2 Try file(description=”stdin”). The 4 codes are same.
readLines(con=file(description="stdin"))
readLines(con="stdin")
scan(file=file(description="stdin"), what=character())
scan(file="stdin", what=character())
# 3 Try readline()
readline(prompt="please enter: ")
经尝试,file(description=”stdin”)可以解决这个问题。具体情况如下图。
After some attempts, I found that ‘file(description=”stdin”)’ can solve this problem. See the picture below for details.
3
但是,在不使用pipe的时候,怎么避免Rscript提示输入呢?经尝试,为file()函数指定参数blocking=FALSE管用。具体情况如下图。
However, when not using pipe, how to avoid Rscript prompts for input? After some attempts, I found that specifying “blocking=FALSE” for file() will help. See the picture below for details.
4 结论
4 conclusion
为了让Rscript既接收命令后面的参数,又接收管道传过来的参数,可以同时使用commandArgs()和readLines(con=file(description=”stdin”, blocking=FALSE))。示例代码如下图。
To make Rscript receives both arguments afterwards and arguments passed via a pipe, you can use both commandArgs() and readLines(con=file(description=”stdin”, blocking=FALSE)). See the picture below for demo codes.