【问题标题】:bash echo with escape backtick and $带有转义反引号和 $ 的 bash 回声
【发布时间】:2019-05-25 00:40:01
【问题描述】:

test.sh

COMMAND1="Build `date`"
COMMAND2="echo $PATH"

echo "Command1 is: $COMMAND1"
echo "Command2 is: $COMMAND2"

输出

Command1 is: Build Wed Dec 26 21:09:43 UTC 2018
Command2 is: echo /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

在上面的 shell 脚本中,如何在不评估表达式的情况下回显,即我想要 Command1 is: Build `date`

我知道我可以转义 `$ 字符,但在我的应用程序中它们来自上游服务并作为参数传递给 shell 脚本。甚至上游服务也无法逃脱它们,因为稍后在脚本中我实际上需要执行这些命令。

理想的方法是告诉 echo 仅扩展变量 $COMMAND1,但不要评估其中的任何内容。或者使用 sed 来转义所有出现的`$,但我都没有实现。

【问题讨论】:

  • 请注意,将命令存储在字符串变量中被认为是不好的做法——它天生就容易出错。请参阅BashFAQ #50,了解有关它如何以及为何出现问题以及可用替代方案的讨论。
  • @CharlesDuffy 感谢您的链接。 set -x 选项很有趣。我会试试的。

标签: shell sed sh echo


【解决方案1】:

表达式在赋值时求值。

COMMAND1="Build `date`"

` ... ` 代表命令替换(它已弃用,取而代之的是 $( ... ))。 \" 引号用于允许文本被扩展。所以首先这个命令被扩展为:

COMMAND1='Build Wed Dec 26 21:09:43 UTC 2018'

然后分配发生。您以后无法检索用于声明变量的命令。该信息丢失。如果您有一些上游 - 它需要将此信息传递给您。

如果您希望COMMAND1 包含字符串(字面意思)

Build `date`

你可以使用单引号:

COMMAND1='Build `date`'

您可以稍后使用eval 或类似的组合来扩展变量,但我建议只做一个函数

COMMAND1() {
   Build $(date)
}

echo "COMMAND1 is declared as:"
declare -f COMMAND1
echo "COMMAND1 execution returns: $(COMMAND1)"

有用的链接:

【讨论】:

  • 哇,这太完美了。因此,您使用单引号然后eval 的建议非常有效。我不明白您使用函数的第二个建议。我也在高山,所以declare 不适合我。 declare 的任何其他替代方案?在我接受您的回答之前,请给我一些时间进行更多实验。谢谢。
  • Busybox 的 shell 是 posix shell 的受限版本。我在 docker 上发现有 type,但没有任何东西可以打印函数声明。对于内置声明,您需要安装 bash。如果你选择eval - 准备好正确地转义你的命令。也许更好的解决方案是子shell sh -c "$COMMAND" 也会对参数进行双重解释,并且如果命令不应该影响当前环境则可以工作。
  • 如果您确实需要稍后评估date,我将重组代码并定义一个函数,当您最终准备好约会时调用该函数。尽可能避免eval
猜你喜欢
  • 2017-07-26
  • 1970-01-01
  • 1970-01-01
  • 2016-07-08
  • 1970-01-01
  • 1970-01-01
  • 2021-02-26
  • 2020-03-21
  • 1970-01-01
相关资源
最近更新 更多