Reputation: 1071
I am working on a .Rmd
document where we show people how to use the command line. This includes bash-based code blocks like this:
```{bash}
echo "this is a test"
```
However, we would like to parameterize this, so have something like
---
params:
testparam: "this would echo something else"
---
```{bash}
echo params$testparam
```
This doesn't work, however, because inside a bash
code block the parameters don't exist.
Is there a way to use parameters in such cases, in essence evaluating params$testparam
before knitr considers the fact that it's inside a non-R code block?
Ideally, the solution would make the following possible:
```{bash}
echo params$testparam
```
turns into
<pre class="bash"><code>echo "this would echo something else"</code></pre>
<pre><code>## this would echo something else</code></pre>
Upvotes: 2
Views: 163
Reputation: 10253
The following .Rmd
may suffice? I use the system()
within a R
block:
---
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")
```
Strong inspiration from here. Of course, the bash command is not readily visible, but I suspect one can work around that.
EDIT:
With a bit of a work-around/hack, you can render the bash code in the following manner:
```{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")
```
So we generate the bash code as a character
and cat
the bash code wrapped in appropriate html while telling knitr to interpret the result 'asis'
(making the results appear as code). As we also suppress the R code itself (echo=FALSE
), the results appear as code only.
Next, in the subsequent chunk, we again suppress the printing of the code but get the output of the system command which is interpreted in the standard manner.
You can of course utilize the trick from @r2evans together with this as well.
Upvotes: 1
Reputation: 160952
As I hoped, this small hack works:
---
params:
testparam: "this would echo something else"
---
```{r, echo = FALSE, include = FALSE}
if (length(params) > 0) do.call(Sys.setenv, params)
```
```{bash}
echo $testparam
```
Yielding
<pre class="bash"><code>echo $testparam</code></pre>
<pre><code>## this would echo something else</code></pre>
This will fail if you pass non-simple objects. I haven't tested vectors/lists/frames, though I suspect they will fail spectacularly ... but since you're using bash
in that chunk, I'm assuming its parameters are less-complex.
If you have some params that are complex but never to be used in your bash chunks, you might consider a naming convention, something like:
---
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
```
which yields
<pre class="bash"><code>echo $testparam</code></pre>
<pre><code>## this would be one thing</code></pre>
Upvotes: 2