【问题标题】:Better string interpolation in RR中更好的字符串插值
【发布时间】:2015-06-08 13:54:13
【问题描述】:

我需要在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]")

【问题讨论】:

  • 可能this post会帮助你
  • IMO 只需为此使用 Python 或 Bash。 R 中的字符串操作很粗糙
  • @ssdecontrol 我已经在 R 中执行了一些带有 IO 操作的命令。他们还使用了一些 R 包,所以我想在 R 中完成其余的工作。但是你是对的,不应该对所有事情都使用 R .

标签: r string-interpolation


【解决方案1】:

有关 tidyverse 解决方案,请参阅 https://github.com/tidyverse/glue。示例

name="Foo Bar"
glue::glue("How do you do, {name}?")

【讨论】:

    【解决方案2】:

    随着版本 1.1.0(CRAN 于 2016-08-19 发布),stringr 包获得了字符串插值函数str_interp(),这是the gsubfn package 的替代方法。

    # 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"
    

    【讨论】:

    • 这有一个缺点,如果您需要像在这种情况下那样按键值进行插值,则列表需要同时提供所有元素,然后一次性插入它们,您无法插入一个接一个,这在不同的场景中可能很有用。
    • @intael 感谢您的反馈,但我不明白您在追求什么,以及为什么您只选择并否决了这个答案。 (1) 这个答案类似于其他使用不同工具插值的答案。 (2) 它按照用户的要求去做——不多也不少。
    【解决方案3】:

    这非常接近您的要求。当任何函数 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"
    

    【讨论】:

    • 选择这个答案是因为它展示了如何在命令行中使用复杂变量(例如 df$colum5[4])。
    • 为什么叫fn$identity?
    • 如果 f 是任何函数,那么 fn$f(...whatever...)` 将导致 f 的参数被插值,如帮助文件中进一步讨论的那样:@987654331 @.
    【解决方案4】:

    另一种选择是使用 https://github.com/edwindj/whisker 中的 whisker.render,这是 R 中的 {{Mustache}} 实现。使用示例:

    require(dplyr); require(whisker)
    
    bedFile="test.bed"
    whisker.render("processing {{bedFile}}") %>% print
    

    【讨论】:

      【解决方案5】:

      不是真正的字符串插值解决方案,但仍然是解决问题的一个很好的选择是使用 processx 包而不是 system() 然后你不需要引用任何东西。

      【讨论】:

        【解决方案6】:
        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

        【讨论】:

        • 感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。 proper explanation would greatly improve its long-term value 通过展示为什么这是一个很好的解决问题的方法,并将使其对未来有其他类似问题的读者更有用。请edit您的回答添加一些解释,包括您所做的假设。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多