如何在单引号或双引号内扩展变量

如何在单引号或双引号内扩展变量

我有 2 个系统,它们具有相同的目录结构。我想在本地系统上执行几个命令,并在远程系统上执行相同的命令。

我使用通配符,因此当我有新版本的包时,我不需要再次编辑 bash 脚本!

我的 bash 脚本有这样几行:

varWheelsDir="/tmp/wheels"
set -x
# Install local
pip3 install --force-reinstall --user "${varWheelsDir}/bbw"*
# Install remote
ssh -t admin@otherhost "pip3 install --user '${varWheelsDir}/bbw$*'"

这也展开

+ pip3 install --user /tmp/wheels/bbw-2.10.0-py3-none-any.whl
+ ssh -t admin@otherhost 'pip3 install --user '\''/tmp/wheels/bbw'\'''

显然,SSH 线路的扩展不起作用。

知道如何将其输入ssh -t

答案1

显然,SSH 线路的扩展不起作用。

撇开该语句中的语法问题不谈,扩展“不起作用”这一点并不明显,只是它没有达到您的预期。如果您包含了它是如何扩展的以及您期望什么,那将会有所帮助。

我怀疑您的意思是您希望扩展发生在远程主机上而不是 ssh 客户端上。在这种情况下,您只需转义传递给本地 shell 的参数 - 但您还需要更改引用以允许远程扩展:

ssh -t admin@otherhost "pip3 install --user \"\${varWheelsDir}/bbw\*\""

答案2

您必须检查当 ssh 命令为“build”时扩展了哪些部分,结果是什么,以及在远程主机上执行该命令时扩展了哪些内容。

对于您的第一次尝试

ssh -t admin@otherhost "pip3 install --user '${varWheelsDir}/bbw$*'"
# expands to
ssh -t admin@otherhost "pip3 install --user '/tmp/wheels/bbw'"
# and executes on the other host
pip3 install --user '/tmp/wheels/bbw'

$*扩展到位置参数,这里可能没有。看https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html#index-_002a

如果你这样做

ssh -t admin@otherhost "pip3 install --user '${varWheelsDir}/bbw'*"
# it should expand to
ssh -t admin@otherhost "pip3 install --user '/tmp/wheels/bbw'*"
# which executes on the other host
pip3 install --user '/tmp/wheels/bbw'*

(请注意, is*位于双引号内以防止在本地主机上进行通配,但位于单引号之外以在远程主机上进行文件通配)

我厌倦了

x=/tmp
ssh -t otherhost "ls -l '$x/'*"

为我工作并列出了远程主机上 temp 中的所有目录。

答案3

许多系统都有AcceptEnv LC_*sshd配置,因此您可以执行以下操作:

export LC_DIR="$varWheelsDir"
shell_code='
  pip3 install --force-reinstall --user "$LC_DIR"/bbw*
'
eval "$shell_code" # interpreted by current shell

ssh -e SendEnv=LC_DIR -t admin@otherhost "$shell_code"
  # interpreted by the login shell of admin on otherhost,
  # assuming it is Bourne-like

使用相同的 shell 代码在本地和远程运行,并共享$LC_DIR具有相同内容的变量。

或者,如果本地 shell 是 zsh 并且您知道adminon的登录 shell 与 Bourne 类似,则可以构造 shell 代码,其中以安全的方式嵌入和引用otherhost本地变量的内容:$varWheelsDir

pip3 install --force-reinstall --user "${varWheelsDir}"/bbw* # local
ssh -t admin@otherhost "
  pip3 install --force-reinstall --user ${(qq)varWheelsDir}/bbw"* # remote

where使用单引号引用 sh 语法中${(qq)var}的内容($var引用任意数据的最安全形式)。

最新版本的bash具有${var@Q}扩展$var、引用的运算符,但在某些情况下它会生成不可移植的 bash 特定语法,并且不仅使用单引号,因此只有当adminon的登录 shellotherhost碰巧是bash(最好是相同的版本并在相同的区域设置中运行)。

如果您不能保证adminon的登录 shellotherhost与 Bourne 类似,请参阅如何在不知道远程用户的登录 shell 的情况下通过 ssh 执行任意简单命令?可能的方法。

相关内容