如何在命令行(终端)上最佳使用R脚本?

137

使用R脚本从命令行绘制简单图形非常方便。然而,从bash脚本运行R并不方便。理想情况可能是这样的:

#!/path/to/R
...
或者
#!/usr/bin/env R
...

但我没有能够让它们中的任何一个工作。

另一种选择是完全使用R编写脚本,例如 script.R,然后使用 R --file=script.R 或类似命令调用它。 但是,有时候脚本会依赖于晦涩难懂的命令行开关,这时代码的一部分存在于脚本之外。例如:通过本地 .Rprofile 从 bash 将东西偷偷传入 R,所需的开关就是除了 --no-init-file 以外 --vanilla 所包含的所有内容。

另一种选择是编写一个 bash 脚本来存储 R 标志并轻松执行,然后调用 R 脚本。问题在于这意味着单个程序被拆分成两个文件,现在必须将它们保持同步,并一起转移到新机器等等。

我目前最不喜欢的选项是将 R 嵌入到 bash 脚本中:

#!/bin/bash
... # usage message to catch bad input without invoking R
... # any bash pre-processing of input
... # etc
R --random-flags <<RSCRIPT
# R code goes here
RSCRIPT

所有的东西都在一个单独的文件中。它是可执行的,并且很容易处理参数。问题是将bash和R组合在一起几乎消除了任何IDE不失败于其中之一的可能性,并且使我的心真的很痛。

我是否有所遗漏?

11个回答

160

script.r文件的内容:

#!/usr/bin/env Rscript

args = commandArgs(trailingOnly = TRUE)
message(sprintf("Hello %s", args[1L]))

第一行是 shebang line。最好使用 /usr/bin/env Rscript,而不是硬编码 R 安装路径。否则,您的脚本可能会在其他计算机上出现故障。

接下来,在命令行上使其可执行:

chmod +x script.r

从命令行调用:

./script.r world
# Hello world

1
是的,我认为这是“官方”的做法。 - Frank
5
在命令行中运行 Rscript --help 将列出许多有用的选项,可以添加到 shebang 中,例如 --vanilla - flodel
8
还有commandArgs函数、getoptoptparse包可用于解析命令行参数。这样在从命令行运行脚本时,参数和选项也可以被传递到脚本中。 - flodel
3
请注意,这仅适用于 #!/usr/bin/Rscript(这不是 R 脚本的标准做法)。 - gented

18

试试littlerlittler为GNU R提供哈希-帮助(即以#!/some/path开头的脚本)功能,以及简单的命令行和管道使用。


12

Miguel Sanchez的回应是正确的。另一种执行Rscript的方法是使用'env'命令来运行系统范围内的RScript。

#!/usr/bin/env Rscript

1
不是“系统范围内”,而是env将允许您运行在自己的$PATH中找到的第一个Rscript,从而允许您实际运行一些与系统范围/默认Rscript(可能未安装在/usr/whatever中)不同的东西。我建议对于RRscript等内容使用env,因为这些内容特别可能未安装在标准位置。 (然而,普通的bash脚本通常可以安全地始终使用#!/bin/bash。) - michael
@michael 不,你在Bash方面是错误的,这是危险的建议。唯一可以安全硬编码的是 /bin/sh。其他所有内容都必须使用 env 查找。特别是,在计算集群上,Bash通常已经过时,用户有自己的定制安装(通常在 ~/.local/bin 中,或者共享在类似于 /software 的NFS挂载中)。同样,在macOS上,/bin/bash 由于许可问题始终过时,最新的Bash更常见地位于 /usr/local/bin/bash(我知道你的评论已经3年了,但这相当重要)。 - Konrad Rudolph
不好意思,那并不是真的。你对这个问题有强烈的看法,所以我不会就此进行辩论。如果在任何情况下使用/bin/sh都不是“危险”的,那么您必须承认同样的事情也适用于/bin/bash。由于不同用户的可靠/不一致的PATH设置,使用env更加不可预测,但是每个R用户实际上可能希望出现这种行为,而bash脚本则不会。最后,对于CI / cloud调用较新的bash脚本,只需使用/path/to/my/bash myscript来调用它们,或者显式地设置路径并使用env script来调用它们。EOT - michael

9

#!/path/to/R无法工作,因为R本身也是一个脚本,所以execve会出现问题。

我使用R --slave -f script


5
给普通读者提个醒:如果你好奇的话,很多这些答案都是在Rscript(和littler)出现之前回答的。 - michael
2
@michael 这里没有任何答案早于Rscript,它是在2007年随着R 2.5.0发布的。 - Konrad Rudolph

7

4

这个可以运行,

#!/usr/bin/Rscript

但是我不知道在您的机器上安装了多个R版本会发生什么。

如果您这样做

#!/usr/bin/env Rscript

它告诉解释器只使用你路径上首次出现的R。


2

在这篇文章中,需要补充一点内容。较新版本的R似乎将Rscript文件藏得比较深。对于2015年1月下载的OSX上的R 3.1.2-1版本,我发现Rscript文件在以下路径:

/sw/Library/Frameworks/R.framework/Versions/3.1/Resources/bin/Rscript

所以,不要像这样使用#! /sw/bin/Rscript,我需要在脚本顶部使用以下代码。

#! /sw/Library/Frameworks/R.framework/Versions/3.1/Resources/bin/Rscript
locate Rscript 可能对你有所帮助。

1
这个答案可能会有所帮助,因为不清楚OP指的是哪个平台(*nix还是Mac OS)。稍加修改(格式化代码并删除道歉开头),这将成为这里答案的一个很好的补充。 - BenBarnes
2
这是使用 #!/usr/bin/env Rscript 而不是在 R 脚本中硬编码路径(并将该长路径添加到 $PATH)的另一个原因。 - michael

2
如果您使用的程序需要参数来执行脚本,您可以将它们放在 #! 行的末尾:
#!/usr/bin/R --random --switches --f

我不熟悉R语言,无法进行适当的测试,但这似乎是有效的:

axa@artemis:~$ cat r.test
#!/usr/bin/R -q -f
error
axa@artemis:~$ ./r.test
> #!/usr/bin/R -q -f
> error
Error: object "error" not found
Execution halted
axa@artemis:~$

0
你可能想使用Python的rpy2模块。然而,正确的方法是使用R CMD BATCH。你可以修改它以写入STDOUT,但默认情况下会写入一个.Rout文件。请参见以下示例:
[ramanujan:~]$cat foo.R
print(rnorm(10))
[ramanujan:~]$R CMD BATCH foo.R
[ramanujan:~]$cat foo.Rout

R version 2.7.2 (2008-08-25)
Copyright (C) 2008 The R Foundation for Statistical Computing
ISBN 3-900051-07-0

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.

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.

[Previously saved workspace restored]


 ~/.Rprofile loaded.
Welcome at  Fri Apr 17 13:33:17 2009
> print(rnorm(10))
 [1]  1.5891276  1.1219071 -0.6110963  0.1579430 -0.3104579  1.0072677 -0.1303165  0.6998849  1.9918643 -1.2390156
>

Goodbye at  Fri Apr 17 13:33:17 2009
> proc.time()
   user  system elapsed
  0.614   0.050   0.721

注意: 你需要尝试使用 --vanilla 和其他选项来移除所有的启动冗余信息。

0

尝试使用smallR在命令行中编写快速的R脚本:

http://code.google.com/p/simple-r/

(目录中的r命令)

使用smallR从命令行绘图将如下所示:

r -p file.txt

3
与其使用似乎已经停止更新的工具,更好的选择是使用仍然活跃的 littler;或者直接使用比 littler 更晚发布的 Rscript 工具。 - michael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接