【问题标题】:Parameterize non-executed code block in Rmd参数化 Rmd 中未执行的代码块
【发布时间】:2019-03-28 18:03:04
【问题描述】:

我正在编写一个.Rmd 文档,向人们展示如何使用命令行。这包括像这样的基于 bash 的代码块:

```{bash}
echo "this is a test"
```

但是,我们想参数化它,所以有类似的东西

---
params:
    testparam: "this would echo something else"
---

```{bash}
echo params$testparam
```

但是,这不起作用,因为在 bash 代码块内不存在参数。 有没有办法在这种情况下使用参数,本质上评估params$testparam之前 knitr 考虑它在非 R 代码块内的事实?

理想情况下,该解决方案可以实现以下目标:

```{bash}
echo params$testparam
```

变成

<pre class="bash"><code>echo "this would echo something else"</code></pre>
<pre><code>## this would echo something else</code></pre>

【问题讨论】:

  • (未经测试)如果这将由knitr 进行预处理,您可能有第一个r 块来执行类似do.call(Sys.setenv, params) 的操作?它可能会转移,不确定。

标签: r r-markdown knitr


【解决方案1】:

正如我所希望的,这个小技巧很有效:

---
params:
    testparam: "this would echo something else"
---

```{r, echo = FALSE, include = FALSE}
if (length(params) > 0) do.call(Sys.setenv, params)
```

```{bash}
echo $testparam
```

产量

<pre class="bash"><code>echo $testparam</code></pre>
<pre><code>## this would echo something else</code></pre>

如果您传递非简单对象,这将失败。我还没有测试过向量/列表/帧,虽然我怀疑它们会严重失败......但是由于您在该块中使用bash,我假设它的参数不那么复杂。

如果您有一些复杂但永远不会在 bash 块中使用的参数,您可以考虑使用命名约定,例如:

---
params:
    bashtestparam: "this would be one thing"
    testparam: "this would echo something else"
---

```{r, echo = FALSE, include = FALSE}
p <- params[ grepl("^bash", names(params)) ]
names(p) <- gsub("^bash", "", names(p))
if (length(p) > 0) do.call(Sys.setenv, p)
```

```{bash}
echo $testparam
```

产生

<pre class="bash"><code>echo $testparam</code></pre>
<pre><code>## this would be one thing</code></pre>

【讨论】:

  • 我刚刚修复了一个小错误,如果没有params(或p 中没有匹配 params)会出错。
  • 这太好了,谢谢!我剩下的问题,就像@Anders 的回答一样,如何将testparam 的值放入代码块中。在您的回答中,代码块读取echo $testparam,但我想向人们展示如果他们写入echo "this would be one thing" 会发生什么,我不知道在那里做什么。
  • 那是另一回事......可能需要编织一个子文档并将其输出包含到当前文档中。见knitr::knit_child,我想。
  • 谢谢,那我去看看。我很抱歉一开始没有更清楚。
【解决方案2】:

以下.Rmd可能就够了吗?我在R 块中使用system()

---
output: html_document
params:
    testparam: "this would echo something else"
---

# Header

Some text.

```{bash}
echo "this is a test"
```

Some more text.

```{r}
cat(system(paste0("echo '", params$testparam, "'"), intern = TRUE), sep = "\n")
```

来自here.的强烈灵感 当然,bash 命令不是很容易看到的,但我怀疑可以解决这个问题。

编辑:

通过一些变通/破解,您可以按以下方式呈现 bash 代码:

```{r bashCode, results="asis", echo=FALSE}
bash_code <- sprintf("echo '%s'", params$testparam)
cat("<pre class='bash'><code>",
    bash_code,
    "</code></pre>")
```

```{r bashOutput, echo=FALSE}
cat(system(bash_code, intern = TRUE), sep = "\n")
```

所以我们将 bash 代码生成为 charactercat 将 bash 代码包装在适当的 html 中,同时告诉 knitr 解释结果 'asis'(使结果显示为代码) .由于我们还抑制了 R 代码本身 (echo=FALSE),因此结果仅显示为代码。 接下来,在随后的块中,我们再次抑制代码的打印,但得到以标准方式解释的系统命令的输出。

当然,您也可以同时利用 @r2evans 的技巧。

【讨论】:

  • 这行得通,几乎正是我想要的。但是 bash 命令不可见是我确实需要解决的问题,我不确定如何解决。由于我可能会在您的解决方案上方使用eval=FALSE 的附加代码块中执行此操作,我将如何将params$testparam 放入其中?
猜你喜欢
  • 2017-09-22
  • 2014-12-15
  • 1970-01-01
  • 2018-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-19
  • 1970-01-01
相关资源
最近更新 更多