【问题标题】:Assignment issue with Rscript -e callsRscript -e 调用的分配问题
【发布时间】:2016-04-01 23:58:48
【问题描述】:

当使用多行字符串参数从命令行外部调用 R 时,谁能解释这种行为?

$ Rscript -e "dim(mtcars)"
[1] 32 11
$ Rscript -e "df = mtcars; dim(df)"
[1] 32 11
$ Rscript -e "head(rownames(mtcars))"
[1] "Mazda RX4"         "Mazda RX4 Wag"     "Datsun 710"
[4] "Hornet 4 Drive"    "Hornet Sportabout" "Valiant"
$ Rscript -e "df = mtcars; df$car = rownames(mtcars); dim(df)"
NULL

【问题讨论】:

  • 次要:将其称为“多语句字符串参数”而不是“多行字符串参数”会更正确。

标签: r


【解决方案1】:

这里的罪魁祸首是shell,而不是R。

您没有指明您使用的是什么 shell,但它们 (sh/bash/ash/dash/ksh/zsh/tcsh) 的行为与我们的目的非常相似,因此假设您使用的是 bash,所以我可以引用一半的bash man page

...

定义

     本文档的其余部分使用以下定义。

...

         name      仅由字母数字字符和下划线组成并以字母字符或下划线开头的单词。也称为标识符。

...

报价

...

     用双引号括起来的字符会保留引号内所有字符的字面值,但 $、`、\ 以及启用历史扩展时的 ! 除外。字符 $ 和 ` 在双引号中保留其特殊含义。

...

参数

     参数是存储值的实体。它可以是名称、数字或下面特殊参数下列出的特殊字符之一。变量是由名称表示的参数。

...

     参数扩展

         `$' 字符引入了参数扩展、命令替换或算术扩展。要扩展的参数名称或符号可以用大括号括起来,这是可选的,但用于保护要扩展的变量免受紧随其后的字符的影响,这些字符可以解释为名称的一部分。

...

     ${参数}

         参数的值被替换。当参数是一个多于一位的位置参数时,或者当参数后跟一个不被解释为其名称的一部分的字符时,大括号是必需的。该参数是上面描述的shell参数(PARAMETERS)或数组引用(Arrays)。

...

因此,参数扩展在双引号字符串中生效,并且双引号字符串中有一个未转义的美元,后跟一个有效的变量名:$car

我推断变量 $car 在您运行有问题的命令的 shell 会话中未设置。

不幸的是,shell 的默认行为是将未设置的变量默默地扩展为空字符串。因此,您的 R 代码最终会变成这样:

df = mtcars; df = rownames(mtcars); dim(df)

因此,df 被无量纲字符向量覆盖,dim(df) 在此类向量上返回 NULL。

问题可以通过反斜杠转义美元来解决:

Rscript -e "df <- mtcars; df\$car <- rownames(mtcars); dim(df);";
## [1] 32 12

或者更好的是,使用单引号,它不允许任何插值发生在单引号字符串中:

Rscript -e 'df <- mtcars; df$car <- rownames(mtcars); dim(df);';
## [1] 32 12

就我个人而言,IMO 似乎很少有工程师了解严格在软件设计中的重要性。如果 shell 从一开始就被设计为拒绝未设置的变量,这对计算机编程专业来说将是一项伟大的服务,但可惜,事实并非如此。所以像你我这样的可怜人,基本上所有做过 shell 编程的人都会不时遇到这些无声的错误。

幸运的是,早期的 shell 中添加了一个可选功能,称为 nounset

help set| grep -e nounset -e -u;
##               nounset      same as -u
##       -u  Treat unset variables as an error when substituting.

如果你打开它,我强烈建议你这样做,那么有问题的 Rscript 命令将立即且明显地失败:

set -u;
Rscript -e "df <- mtcars; df$car <- rownames(mtcars); dim(df);";
## -bash: car: unbound variable

【讨论】:

  • 正确答案,而且非常详细。简而言之,' 是你的朋友,因为它没有插值。
猜你喜欢
  • 2011-10-15
  • 1970-01-01
  • 2012-10-02
  • 1970-01-01
  • 2011-12-17
  • 2015-09-10
  • 2017-06-08
  • 1970-01-01
  • 2014-11-06
相关资源
最近更新 更多