R 中更好的字符串插值
Better string interpolation in R
我需要在 R
中构建长命令行并将它们传递给 system()
。我发现使用 paste0/paste
函数非常不方便,甚至 sprintf
函数来构建每个命令行。有没有更简单的方法:
而不是这个难以阅读和太多的引用:
cmd <- paste("command", "-a", line$elem1, "-b", line$elem3, "-f", df$Colum5[4])
或:
cmd <- sprintf("command -a %s -b %s -f %s", line$elem1, line$elem3, df$Colum5[4])
我可以要这个吗:
cmd <- buildcommand("command -a %line$elem1 -b %line$elem3 -f %df$Colum5[4]")
这与您的要求非常接近。当任何函数 f 以 fn$ 开头时,即 fn$f,将执行字符插值,将 ...
替换为 运行 的结果 ... 作为 R 表达式。
library(gsubfn)
cmd <- fn$identity("command -a `line$elem1` -b `line$elem3` -f `df$Colum5[4]`")
这是一个独立的可重现示例:
library(gsubfn)
# test inputs
line <- list(elem1 = 10, elem3 = 30)
df <- data.frame(Colum5 = 1:4)
fn$identity("command -a `line$elem1` -b `line$elem3` -f `df$Colum5[4]`")
## [1] "command -a 10 -b 30 -f 4"
系统
因为可以使用任何函数,所以我们可以像这样直接对 system
调用进行操作。我们在这里使用 echo
使其可执行,但可以使用任何命令。
exitcode <- fn$system("echo -a `line$elem1` -b `line$elem3` -f `df$Colum5[4]`")
## -a 10 -b 30 -f 4
变化
这个变体也可以。 fn$f 还执行用变量 whatever 的值替换 $whatever。有关详细信息,请参阅 ?fn
。
with(line, fn$identity("command -a $elem1 -b $elem3 -f `df$Colum5[4]`"))
## [1] "command -a 10 -b 30 -f 4"
在 1.1.0 版本(CRAN 于 2016-08-19 发布)中,stringr
包获得了一个字符串插值函数 str_interp()
,它是 的替代方法。
# sample data
line <- list(elem1 = 10, elem3 = 30)
df <- data.frame(Colum5 = 1:4)
# do the string interpolation
stringr::str_interp("command -a ${line$elem1} -b ${line$elem3} -f ${df$Colum5[4]}")
#[1] "command -a 10 -b 30 -f 4"
另一种选择是使用 https://github.com/edwindj/whisker 中的 whisker.render
,它是 R 中的 {{Mustache}} 实现。用法示例:
require(dplyr); require(whisker)
bedFile="test.bed"
whisker.render("processing {{bedFile}}") %>% print
有关 tidyverse 解决方案,请参阅 https://github.com/tidyverse/glue。例子
name="Foo Bar"
glue::glue("How do you do, {name}?")
library(GetoptLong)
str = qq("region = (@{region[1]}, @{region[2]}), value = @{value}, name = '@{name}'")
cat(str)
qqcat("region = (@{region[1]}, @{region[2]}), value = @{value}, name = '@{name}'")
https://cran.r-project.org/web/packages/GetoptLong/vignettes/variable_interpolation.html
不是真正的字符串插值解决方案,但仍然是解决该问题的一个很好的选择是使用 processx 包而不是 system()
然后你不需要引用任何东西。
我需要在 R
中构建长命令行并将它们传递给 system()
。我发现使用 paste0/paste
函数非常不方便,甚至 sprintf
函数来构建每个命令行。有没有更简单的方法:
而不是这个难以阅读和太多的引用:
cmd <- paste("command", "-a", line$elem1, "-b", line$elem3, "-f", df$Colum5[4])
或:
cmd <- sprintf("command -a %s -b %s -f %s", line$elem1, line$elem3, df$Colum5[4])
我可以要这个吗:
cmd <- buildcommand("command -a %line$elem1 -b %line$elem3 -f %df$Colum5[4]")
这与您的要求非常接近。当任何函数 f 以 fn$ 开头时,即 fn$f,将执行字符插值,将 ...
替换为 运行 的结果 ... 作为 R 表达式。
library(gsubfn)
cmd <- fn$identity("command -a `line$elem1` -b `line$elem3` -f `df$Colum5[4]`")
这是一个独立的可重现示例:
library(gsubfn)
# test inputs
line <- list(elem1 = 10, elem3 = 30)
df <- data.frame(Colum5 = 1:4)
fn$identity("command -a `line$elem1` -b `line$elem3` -f `df$Colum5[4]`")
## [1] "command -a 10 -b 30 -f 4"
系统
因为可以使用任何函数,所以我们可以像这样直接对 system
调用进行操作。我们在这里使用 echo
使其可执行,但可以使用任何命令。
exitcode <- fn$system("echo -a `line$elem1` -b `line$elem3` -f `df$Colum5[4]`")
## -a 10 -b 30 -f 4
变化
这个变体也可以。 fn$f 还执行用变量 whatever 的值替换 $whatever。有关详细信息,请参阅 ?fn
。
with(line, fn$identity("command -a $elem1 -b $elem3 -f `df$Colum5[4]`"))
## [1] "command -a 10 -b 30 -f 4"
在 1.1.0 版本(CRAN 于 2016-08-19 发布)中,stringr
包获得了一个字符串插值函数 str_interp()
,它是
# sample data
line <- list(elem1 = 10, elem3 = 30)
df <- data.frame(Colum5 = 1:4)
# do the string interpolation
stringr::str_interp("command -a ${line$elem1} -b ${line$elem3} -f ${df$Colum5[4]}")
#[1] "command -a 10 -b 30 -f 4"
另一种选择是使用 https://github.com/edwindj/whisker 中的 whisker.render
,它是 R 中的 {{Mustache}} 实现。用法示例:
require(dplyr); require(whisker)
bedFile="test.bed"
whisker.render("processing {{bedFile}}") %>% print
有关 tidyverse 解决方案,请参阅 https://github.com/tidyverse/glue。例子
name="Foo Bar"
glue::glue("How do you do, {name}?")
library(GetoptLong)
str = qq("region = (@{region[1]}, @{region[2]}), value = @{value}, name = '@{name}'")
cat(str)
qqcat("region = (@{region[1]}, @{region[2]}), value = @{value}, name = '@{name}'")
https://cran.r-project.org/web/packages/GetoptLong/vignettes/variable_interpolation.html
不是真正的字符串插值解决方案,但仍然是解决该问题的一个很好的选择是使用 processx 包而不是 system()
然后你不需要引用任何东西。