Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
bash脚本中单引号的问题_Bash - Fatal编程技术网

bash脚本中单引号的问题

bash脚本中单引号的问题,bash,Bash,我正在尝试从bash脚本运行命令。命令本身有单引号,但我无法让它们工作,因为单引号中有需要展开的变量。下面是bash脚本: #!/bin/bash if [ "$2" == "PracSci" ]; then echo "Running tabulate.science.r" R CMD BATCH --no-save --no-restore --slave '--args $1 $2 $3' tabulate.science.r /dev/tty else echo

我正在尝试从bash脚本运行命令。命令本身有单引号,但我无法让它们工作,因为单引号中有需要展开的变量。下面是bash脚本:

#!/bin/bash

if [ "$2" == "PracSci" ];
then
    echo "Running tabulate.science.r"
    R CMD BATCH --no-save --no-restore --slave '--args $1 $2 $3' tabulate.science.r /dev/tty
else
    echo "Running tabulate.r"
    R CMD BATCH --no-save --no-restore --slave '--args $1 $2 $3' tabulate.r /dev/tty
fi
例如,当以
/script.sh 2 Vocab May12
的形式运行时,命令本身不带变量值

如何在运行命令的同时展开变量

为了清楚起见,我尝试运行的命令是:
R CMD BATCH--no save--no restore--slave'--args$1$2$3'制表。R/dev/tty
(包括命令中的单引号)


谢谢大家!

使用双引号-还是我遗漏了要点?

您可以使用“(双引号)来代替,或者用“即”来结束

#!/bin/bash

if [ "$2" == "PracSci" ];
then
    echo "Running tabulate.science.r"
    R CMD BATCH --no-save --no-restore --slave '--args '$1' '$2' '$3 tabulate.science.r /dev/tty
else
    echo "Running tabulate.r"
    R CMD BATCH --no-save --no-restore --slave '--args '$1' '$2' '$3 tabulate.r /dev/tty
fi
或者,如果你需要args…在一个单一的报价再次然后简单地写

#!/bin/bash

if [ "$2" == "PracSci" ];
then
    echo "Running tabulate.science.r"
    R CMD BATCH --no-save --no-restore --slave "'--args $1 $2 $3'" tabulate.science.r /dev/tty
else
    echo "Running tabulate.r"
    R CMD BATCH --no-save --no-restore --slave "'--args $1 $2 $3'" tabulate.r /dev/tty
fi

如果我理解正确,您需要
“--args$1$2$3”“
而不是普通的
”--args$1$2$3'
。由于顶级标记是双引号字符串,变量将被展开,
也将保留在标记中,以便R可以使用它们。

简短回答:使用双引号而不是单引号(如@Pavel建议的)。如果有疑问,请使用
set-x
了解shell是如何解析您的命令的

长回答:引号不会传递给命令;相反,在将参数传递给命令之前,它们由shell解析(并删除)。它们所做的是改变shell解析引号内内容的方式(通常通过抑制某些字符的特殊含义),这意味着您需要选择适当的引号来允许解析您想要解析的特殊字符,并抑制您想要作为普通字符处理的字符。例如,考虑下面的命令:

R CMD BATCH --no-save --no-restore --slave '--args 2 Vocab May12' tabulate.r /dev/tty
shell将忽略命令单引号部分中所有字符的特殊含义。唯一具有特殊意义的字符是空格,通常用作参数之间的分隔符;在本例中,单引号使shell将它们视为单个参数的一部分。这些其他命令:

R CMD BATCH --no-save --no-restore --slave "--args 2 Vocab May12" tabulate.r /dev/tty
R CMD BATCH --no-save --no-restore --slave --args' '2' 'Vocab' 'May12 tabulate.r /dev/tty
R CMD BATCH --no-save --no-restore --slave --args\ 2\ Vocab\ May12 tabulate.r /dev/tty
…它们都做完全相同的事情,因为它们都(以这样或那样的方式)让shell将空格视为参数的一部分,而不是参数之间的分隔符

现在,让我们看看不适用于您的命令:

R CMD BATCH --no-save --no-restore --slave '--args $1 $2 $3' tabulate.r /dev/tty
问题是,虽然单引号抑制了空格的特殊含义(如您所愿),但它们也抑制了
$
s的特殊含义(您不希望)。所以你需要更具选择性的东西。一个选项是引用/转义空格,但将
$1
etc保留为未引用:

R CMD BATCH --no-save --no-restore --slave --args' '$1' '$2' '$3 tabulate.r /dev/tty
R CMD BATCH --no-save --no-restore --slave --args\ $1\ $2\ $3 tabulate.r /dev/tty
(请注意,这两个命令的作用完全相同。)这些命令基本上可以工作,但有一点可能会出现问题:shell将使用脚本的参数替换
$1
等,但随后它会对它们进行一些额外的解析:查找用作参数分隔符的空格、用于文件名匹配的通配符,诸如此类,我很确定你不想要的东西——尽管由于参数可能不包含任何特殊字符,这可能不会成为问题。可能吧

我看到的最佳选择是简单地使用双引号:

R CMD BATCH --no-save --no-restore --slave "--args $1 $2 $3" tabulate.r /dev/tty

双引号抑制空格的特殊含义(如您所愿),允许
$
触发变量扩展(也如您所愿),但在变量扩展后(也可能是您所需)阻止任何进一步的解析。参数中的空格或其他有趣的字符可能仍然会在R脚本中引起问题,但至少这可以防止它们在R脚本启动之前引起问题。

可能不会;使用双引号中的单引号,子进程(可能)会看到单引号,这可能不是必需的。用双引号代替单引号是可行的。这两个建议似乎都不起作用。这两个命令都会导致回显发生,然后脚本在没有R命令的情况下结束。使用
set-x
,使用您的建议,此行的输出是:
++R CMD BATCH--no save--no restore--slave'\''''''''''''''''''''''''''''''-args 2 Vocab May12'\''\''''''''''''''''''''''''''''',\cannot escape'字符在一个单引号内,您应该使用“which has”,而不是在其中。我认为您缺少了单引号需要在实际执行的命令中出现的一点。请参阅我对问题的修改。谢谢!那么Kilian Foth的建议就是解决方法。将“set-x“在您的脚本开始时,我尝试了他的建议,请参阅我在他的文章中对输出的推荐。我怀疑您是否需要单引号。当您从shell运行此命令时,shell将使用它们并将一个不带引号的单词传递给R命令。@glennjackman您肯定需要引号。不使用引号运行它不会产生任何结果。我无法解释,但我已经尝试过了。我同意@glenn jackman;您可能需要某种类型的引号,但引号的作用是改变shell解析其内容的方式——它们对程序本身是不可见的。例如,
somecmd'-args part1 part2 part3'
运行somecmd时使用的参数与
somecmd'-args part1 part2 part3'
somecmd--args''part1''part2''part3'
somecmd-args\part1\part2\part3
完全相同。在所有这些情况下,引号/转义符所做的是使shell将空格视为单个参数的一部分,而不是参数之间的分隔符。@GordonDavisson您概述的反斜杠解决方案有效!非常感谢。这很理想,因为问题似乎在于引号——或者单引号和双引号的组合——是否实际上是已执行命令的一部分。如果