在Bash中的命令中扩展单引号内的变量

我想从一个bash shell脚本运行一个命令,该脚本在单引号和变量中包含单引号和其他一些命令。

例如repo forall -c '....$variable'

在这种格式下, $被转义并且变量不被扩展。

我尝试了以下变化,但他们被拒绝了:

repo forall -c '...."$variable" '

repo forall -c " '....$variable' "

" repo forall -c '....$variable' "

repo forall -c "'" ....$variable "'"

如果我用这个值代替变量,那么命令执行得很好。

请告诉我我哪里错了。


在单引号内,所有内容都保留字面,毫无例外。

这意味着您必须关闭引号,插入内容,然后再次重新输入。

'before'"$variable"'after'
'before'"'"'after'
'before'''after'

正如您可以验证的那样,上述每一行都是一个单词。 字符串连接只是通过并置完成的。 引号(单或双引号,视情况而定),用于禁止的各种特殊字符的解释,如空格, $; ......有关引用的好教程,请参阅Mark Reed的回答。 也相关:哪些字符需要在bash中转义?

不要连接由shell解释的字符串

你应该绝对避免通过连接变量来构建shell命令。 这与SQL片段串联(SQL注入!)相似是一个糟糕的主意。

通常可以在命令中包含占位符,并将命令与变量一起提供,以便被调用者可以从调用参数列表中接收它们。

例如,以下是非常不安全的。 不要这样做

script="echo "Argument 1 is: $myvar""
/bin/sh -c "$script"

如果$myvar的内容不可信,这是一个漏洞:

myvar='foo"; echo "you were hacked'

而不是上面的调用,使用位置参数。 以下调用更好 - 它不可被利用:

script='echo "arg 1 is: $1"'
/bin/sh -c "$script" -- "$myvar"

请注意,在script使用单个滴答,这意味着它是从字面上理解的,没有可变扩展或任何其他形式的解释。


repo命令不能关心它得到什么样的引用。 如果您需要参数扩展,请使用双引号。 如果这意味着你不得不反斜线处理大量内容,那么在大部分内容中使用单引号,然后突破它们并在需要扩展的部分进行双打。

repo forall -c 'literal stuff goes here; '"stuff with $parameters here"' more literal stuff'

解释如下,如果你有兴趣。

当你从shell运行命令时,那个命令作为参数接收的是一个以空字符结尾的字符串数组。 这些字符串可能包含绝对的任何非空字符。

但是,当shell从命令行构建字符串数组时,它专门解释了一些字符; 这是为了使命令更容易(实际上可能)输入而设计的。 例如,空格通常表示数组中字符串之间的边界; 出于这个原因,个别论证有时被称为“单词”。 但是一个论点可能还有空间; 你只需要一些方法来告诉shell这就是你想要的。

您可以在任何字符(包括空格或另一个反斜杠)前面使用反斜杠来指示shell从字面上处理该字符。 但是,虽然你可以做这样的事情:

echo "Thank you. That'll be $4.96, please," said the cashier

...它可能会让人厌烦。 所以shell提供了一个替代方案:引号。 这些来自两个主要品种。

双引号被称为“分组引号”。 它们可以防止通配符和别名被扩展,但主要是为了在单词中包含空格。 其他的东西,比如参数和命令扩展(用$表示的东西)仍然会发生。 当然,如果你想在双引号内使用双引号,你必须反斜杠:

echo ""Thank you. That'll be $4.96, please," said the cashier"

单引号更为严格。 它们之间的一切都是完全字面的,包括反斜杠。 绝对没有办法在单引号内使用单引号。

幸运的是,shell中的引号不是单词分隔符, 他们本身并没有终止一个字。 您可以在同一个单词中进出引号(或不同类型的引号之间)以获得期望的结果:

echo '"Thank you. That'''ll be $4.96, please," said the cashier'

所以这很容易 - 反斜杠的数量要少得多,尽管近单引号,反引号,单引号,单引号开放序列需要一些习惯。

现代shell已经添加了POSIX标准未指定的另一种引用样式,其中前导单引号以前缀为美元符号。 如此引用的字符串遵循ANSI C编程语言中字符串文字的类似惯例,因此有时称为“ANSI字符串”和$' ... '对“ANSI引号”。 在这样的字符串中,上述关于反斜杠的忠告不再适用。 相反,它们再次变得特别 - 不仅可以通过向其添加反斜杠来包含文字单引号或反斜线,而且还会扩展ANSI C字符转义符(例如n代表换行符, t代表制表符,并且xHH代表十六进制代码HH )。 否则,它们表现为单引号字符串:不发生参数或命令替换:

echo $'"Thank you.  That'll be $4.96, please," said the cashier'

重要的是要注意的是,作为echo命令的参数接收的单个字符串在所有这些示例中都完全相同。 在完成shell解析命令行之后,运行的命令无法告诉引用的内容。 即使它想。


编辑:(根据评论的问题:)

从那以后我一直在关注这个。 我很幸运,我有回购铺设。 仍然不清楚你是否需要用单引号括起你的命令。 我研究了repo语法,我不认为你需要。 你可以在你的命令周围使用双引号,然后使用你需要的任何单引号和双引号,只要你转义双引号。

链接地址: http://www.djcxy.com/p/24117.html

上一篇: Expansion of variable inside single quotes in a command in Bash

下一篇: Printing asterisk (*) in bash shell