在Rmarkdown中的Bash shell中设置环境变量

8

我希望在Rmarkdown的bash块中设置一个环境变量,并在后续的R块中访问它。本质上,我想做与这个问题相反的事情,这个问题已经被回答了很多次:RMarkdown accessing parameter from bash chunk

我可以使用R将参数传递到bash块中:

Sys.setenv(MY_PARAM = 'param value')

并在bash中访问它:

echo $MY_PARAM

参数值

但是当我尝试在bash中存储环境变量时,我无法在稍后的R中访问它:

再次进入bash:

export MY_PARAM2="param value"
echo $MY_PARAM2

参数值

一个后续的 R 代码块:

Sys.getenv('MY_PARAM2')

[1] " "

如果有其他想法可以从bash代码块中传递变量以在后续块中使用。以下是完整的Rmarkdown代码:

```{r}
Sys.setenv(MY_PARAM = 'param value')
```

```{bash}
echo $MY_PARAM
```

```{bash}
export MY_OTHER_PARAM="param value"
echo $MY_OTHER_PARAM
```

```{r}
Sys.getenv('MY_OTHER_PARAM')
```

1
你可以尝试用自定义系统调用替换 Sys.getenv(...),例如:system(command = 'echo %MY_PARAM2%', intern = TRUE) - Tonio Liebrand
1
好的想法,但没有这样的运气。运行 system(command = 'echo MY_OTHER_PARAM: $MY_OTHER_PARAM') 会产生输出 MY_OTHER_PARAM: - Patrick
我不太理解RMarkdown bash代码块中的环境是什么,或者为什么它似乎与整体环境不同。也许@yihui-xie可以澄清一下? - Patrick
如果您在控制台中运行系统调用(例如其他环境变量,如“PATH”),它是否有效?您使用的是哪个操作系统? - Tonio Liebrand
2个回答

5
在bash中导出的值仅在同一会话中可用。因此,如果R是在同一会话中启动的,则只能看到该值。 如果这对你来说是正确的情况,那么你的问题已经包含了它应该如何工作的答案。这已被证明可以工作,参见this similar question
但是,如果R进程或其子进程在自己的shell中启动,则会话变量(例如MY_OTHER_PARAM)可能对该R进程未知。这可能是由rmarkdown/knitr处理外部命令的方式引起的。您可以使用以下代码片段自行查看此问题:第二个bash会话也不知道导出的变量。Others也报告了这个问题。
```{bash}
export MY_OTHER_PARAM="param value"
echo $MY_OTHER_PARAM
```
```{bash}
echo $MY_OTHER_PARAM
```

所以,最简单的解决方案是将信息存储在特定的文件中,并在后续会话中读取它:
```{bash}
echo 'export MY_OTHER_PARAM="param value"' > .rvars
source .rvars
echo $MY_OTHER_PARAM
```
```{bash}
source .rvars
echo $MY_OTHER_PARAM
```

如果我们已经使用文件,我会跳过环境作为返回路径。
```{bash}
echo 'param value' > .myparam
cat .myparam
```
```{bash}
echo $(cat .myparam)
```

```{r}
string <- paste(readLines(".myparam"), collapse=" ")
print(string)
```

谢谢!我希望有一些不用使用单独文件的方法,但这篇文章写得非常好。 - Patrick
1
考虑使用declare -p param1 param2 ... > .rvars来编写代码,这是一种更好的方式;使用echo(或通过字符串连接等方式)生成代码会存在重大的安全问题。如果你有一个变量,例如myvar=$'$(rm -rf ~)\'$(rm -rf ~)\'',那么无论是echo "myvar=$myvar"还是echo "myvar='$myvar'"都将无法生成重新创建变量而不产生明显意外副作用的代码。 - Charles Duffy

0

据我所知,R在启动时会检查ENV变量,而您的bash会话仅在该会话启动后创建您感兴趣的变量,这将是一个棘手的问题。我猜即使重新启动R会话也无济于事,因为那也会刷新你的bash env。
我建议将您感兴趣的值放入文件中,例如在临时目录中,以后在需要时再将它们读回到您的会话中。
另一种选择是相应地调整.Renviron。


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