在变量中存储选项时的 bash 转义问题

在变量中存储选项时的 bash 转义问题

我有一个字符串存储在变量中。这就是我想要的结果...

cmd="--name=cloudflare-ddns \
--hostname=oznu-cloudflare-ddns \
--env=SUBDOMAIN=private \
--env=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
--env=QEMU_ARCH=x86_64 \
--env=S6_KEEP_ENV=1 \
--env=S6_BEHAVIOUR_IF_STAGE2_FAILS=2 \
--env=CF_API=https://api.cloudflare.com/client/v4 \
--env=RRTYPE=A 
--env='CRON=*/5 *   *   *   *' --env=PROXIED=false \
--env=ZONE=thebiermans.net \
--env=API_KEY=kka \
--network=host \
--restart=always \
--log-driver=db --runtime=runc --detach=true -t oznu/cloudflare-ddns:latest"

如何将其存储在变量中以便我可以执行它?

例如

docker run $CMD

我在这里缺少正确的转义集并且得到错误的输出。

答案1

为了让 shell 评估存储在变量中的 shell 代码,您可以使用eval特殊的内置命令。这与其他几种语言相同:

cmd="--name=cloudflare-ddns \
--hostname=oznu-cloudflare-ddns \
--env=SUBDOMAIN=private \
--env=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
--env=QEMU_ARCH=x86_64 \
--env=S6_KEEP_ENV=1 \
--env=S6_BEHAVIOUR_IF_STAGE2_FAILS=2 \
--env=CF_API=https://api.cloudflare.com/client/v4 \
--env=RRTYPE=A 
--env='CRON=*/5 *   *   *   *' --env=PROXIED=false \
--env=ZONE=thebiermans.net \
--env=API_KEY=kka \
--network=host \
--restart=always \
--log-driver=db --runtime=runc --detach=true -t oznu/cloudflare-ddns:latest"

eval "docker run $cmd"

这假定shell 语法中的有效代码的串联"docker run "和内容。$CMD在这种情况下,对该代码的解释将导致执行docker带有参数列表的命令。

要运行带有存储在变量中的参数列表的命令,您可以使用数组变量:

args=(
  --name=cloudflare-ddns
  --hostname=oznu-cloudflare-ddns
  --env=SUBDOMAIN=private
  --env=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  --env=QEMU_ARCH=x86_64
  --env=S6_KEEP_ENV=1
  --env=S6_BEHAVIOUR_IF_STAGE2_FAILS=2
  --env=CF_API=https://api.cloudflare.com/client/v4
  --env=RRTYPE=A
  --env='CRON=*/5 *   *   *   *'
  --env=PROXIED=false
  --env=ZONE=thebiermans.net
  --env=API_KEY=kka
  --network=host
  --restart=always
  --log-driver=db --runtime=runc --detach=true 
  -t oznu/cloudflare-ddns:latest
)

docker run "${args[@]}"

无论如何,在 bash 中,不要在列表上下文中保留未加引号的参数扩展,因为这几乎不会达到您想要的效果。执行此操作的是 split+glob 运算符,它将变量的内容拆分为字符,$IFS然后对每个结果单词执行文件名生成。这与 shell 语法标记化和语法解析完全无关。例如,识别和解释引号的部分。

相关内容