Linux 从Bash脚本中,如何正确地转义位于命令字符串中的变量?

Linux 从Bash脚本中,如何正确地转义位于命令字符串中的变量?,linux,bash,chocolatey,Linux,Bash,Chocolatey,我正在使用SaltStack运行一个命令,该命令在字符串中包含一个Linux环境变量。 环境变量是$DUO。 例如: 我可以运行以下命令: salt computer chocolatey.install app args='/S /V" /qn '"$DUO"'"' 这将实际生成如下命令: '/S /V" /qn TESTKEY"' 它输出我想要的环境变量 我现在正在运行一个bash脚本,该脚本从用户处获取环境变量并将其放入字符串中: #!/bin/bash echo "What env

我正在使用SaltStack运行一个命令,该命令在字符串中包含一个Linux环境变量。 环境变量是$DUO。 例如:

我可以运行以下命令:

salt computer chocolatey.install app args='/S /V" /qn '"$DUO"'"'
这将实际生成如下命令:

'/S /V" /qn TESTKEY"'
它输出我想要的环境变量

我现在正在运行一个bash脚本,该脚本从用户处获取环境变量并将其放入字符串中:

#!/bin/bash

echo "What env do you want to use?: "
read env

i="\$${env}"
echo $i
salt computer chocolatey.install app args='/S /V" /qn '"${i@Q}"'"'
我的Bash脚本接受用户输入并自动在其前面放置一个“$”。 如果用户输入“DUO”,命令将按以下方式运行:

'/S /V" /qn '$DUO'"'
但我想让它运行这个:

'/S /V" /qn TESTKEY"'
在Bash脚本中,如何正确地转义I变量,以便在命令运行时调用环境变量$DUO

更新

以下是我的实际SaltStack命令:

sudo salt computername chocolatey.install duo override_args=True install_args='/S /V" /qn HOST="xxxxxxx.com" RDPONLY="#0" '"$DUO"'"'
输出:

computername:
    Chocolatey v0.10.15
    Installing the following packages:
    duo
    By installing you accept licenses for the packages.

    duo v0.3
    duo package files install completed. Performing other installation steps.
    Installing Duo...
    Overriding package arguments with '/S /V" /qn HOST="xxxxxxx.com" RDPONLY="#0" TESTKEY"' (replacing '/S /V" /qn HOST="xxxxxxx.com" RDPONLY="#0" "')
    Duo has been installed.
     The install of duo was successful.
      Software installed as 'EXE', install location is likely default.

    Chocolatey installed 1/1 packages. 
     See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log).
更新2

我在调试打开的情况下运行了脚本,而Bash脚本实际上是以以下方式运行的:

+ salt 'computername' chocolatey.install duo override_args=True 'install_args=/S /V" /qn HOST="xxxxx.com" RDPONLY="#0" '\''$DUO'\''"'
更新3

我尝试扩展变量名,但出现了一个错误

bad substitution
例如,这给了我一个错误:

#!/bin/bash

echo "What env do you want to use?: "
read env

i="\$${env}"
echo "${!i}"
间接膨胀 如知识库中其他地方所述,使用
${!env}
展开到
$env
中命名的变量

在这里使用它 …产生的输出与您的示例中的工作巧克力命令完全相同,无需替换:

DUO=TESTKEY
set -x # enable tracing; below : causes us to just trace the command and not run it
: sudo salt computername chocolatey.install duo override_args=True install_args='/S /V" /qn HOST="xxxxxxx.com" RDPONLY="#0" '"${DUO}"'"'
间接膨胀 如知识库中其他地方所述,使用
${!env}
展开到
$env
中命名的变量

在这里使用它 …产生的输出与您的示例中的工作巧克力命令完全相同,无需替换:

DUO=TESTKEY
set -x # enable tracing; below : causes us to just trace the command and not run it
: sudo salt computername chocolatey.install duo override_args=True install_args='/S /V" /qn HOST="xxxxxxx.com" RDPONLY="#0" '"${DUO}"'"'

$DUO
不是有效的变量名,
export$DUO=“TESTKEY”
不是分配此类变量的命令。它需要是
export DUO=“TESTKEY”
(尽管为您自己的变量使用所有caps名称通常不是一个好的做法——POSIX保留至少一个小写字符的名称供应用程序使用,而所有caps变量都可以修改或反映shell本身或POSIX定义的工具的行为).至于shell变量的间接扩展,这在<代码>${i@Q}仅在生成将由另一个shell解析为语法的内容时使用。无论如何,请向我们展示一个行为完全符合您意图的salt命令(在扩展被替换为值之后),然后这将更清楚地说明问题。抱歉,这是一个输入错误。我试着把一切都缩短了。我将发布实际命令和实际输出。谢谢!实际上,更好的方法是使用
set-x
启用跟踪,运行一个工作命令,并提供其跟踪。这样,我们就可以看到shell如何看待当事情按照您的预期运行时所使用的引用。(收集该日志后,可以使用
set+x
关闭跟踪)。
$DUO
不是有效的变量名,并且
export$DUO=“TESTKEY”
不是分配此类变量的命令。它需要是
export DUO=“TESTKEY”
(尽管为您自己的变量使用所有caps名称通常不是一个好的做法——POSIX保留至少一个小写字符的名称供应用程序使用,而所有caps变量都可以修改或反映shell本身或POSIX定义的工具的行为).至于shell变量的间接扩展,这在<代码>${i@Q}仅在生成将由另一个shell解析为语法的内容时使用。无论如何,请向我们展示一个行为完全符合您意图的salt命令(在扩展被替换为值之后),然后这将更清楚地说明问题。抱歉,这是一个输入错误。我试着把一切都缩短了。我将发布实际命令和实际输出。谢谢!实际上,更好的方法是使用
set-x
启用跟踪,运行一个工作命令,并提供其跟踪。这样,我们就可以看到shell如何看待当事情按照您的预期运行时所使用的引用。(收集该日志后,可以使用
set+x
关闭跟踪)。
DUO=TESTKEY
set -x # enable tracing; below : causes us to just trace the command and not run it
: sudo salt computername chocolatey.install duo override_args=True install_args='/S /V" /qn HOST="xxxxxxx.com" RDPONLY="#0" '"${DUO}"'"'