我有 2 个 Shell 脚本。第一个触发第二个并添加一些参数。第二个脚本调用命令并将第一个脚本中的参数添加为该命令的参数。
第一个看起来像:
#!/usr/bin/env bash
ADDITIONAL_ARGUMENTS='--set "args={/bin/bash,-c,cd /var/www && sudo -u www-data bash scripts/system/update.sh}"'
SUPER_PARAMS=${ADDITIONAL_ARGUMENTS} my_second_script.sh
然后,第二个脚本执行以下操作:
#!/usr/bin/env bash
randomBinary --some-hardcoded-parameters \
"${SUPER_PARAMS}"
我期望得到的是以下输出:
randomBinary --some-hardcoded-parameters --set "args={/bin/bash,-c,cd /var/www && sudo -u www-data bash scripts/system/update.sh}"
但相反,调用看起来像:
randomBinary --some-hardcoded-parameters '--set "args={/bin/bash,-c,cd /var/www && sudo -u www-data bash scripts/system/update.sh}"'
我尝试了 2 天正确引用参数,但没有结果。
答案1
要存储多个参数,请使用数组,而不是标量变量。
additional_arguments=(
--set
'args={/bin/bash,-c,cd /var/www && sudo -u www-data bash scripts/system/update.sh}'
)
randomBinary --some-hardcoded-parameters "${additional_arguments[@]}"
请注意,由于环境变量是非 NUL 字节的字符串,因此如果您想通过环境将数组定义传递给另一个命令,则需要进行一些编码。
与ksh
, bash
,zsh
或者yash
您可以使用:
ARRAY_DEFINITION="$(typeset -p additional_arguments)" my_second_script.sh
将数组定义导出到调用脚本的环境变量中。
并eval "$ARRAY_DEFINITION"
在调用的脚本中进口该数组定义。
请注意,重要的是,代码是在与生成代码的语言环境相同的语言环境中并使用相同的 shell 进行计算的。
另请注意,如果在函数内部评估数组定义,则该数组将是该函数的本地数组。
有些 shell 喜欢rc
,es
或fish
允许导出数组(在内部使用它们自己的编码)。
在这里,将信息作为参数传递给被调用的脚本会更容易,因为这是一个数组。
在调用脚本中:
my_second_script.sh "${additional_arguments[@]}"
在调用的脚本中:
randomBinary --some-hardcoded-parameters "$@"
或者调用被调用的脚本,.
以便它共享调用者的 shell 变量,这样您就不需要使用环境在执行过程中传递该数据。
答案2
这里,
randomBinary --some-hardcoded-parameters "${SUPER_PARAMS}"
SUPER_PARAMS
contains --set "args={/bin/bash,-c,cd /var/www && sudo -u www-data bash scripts/system/update.sh}"
,并且由于它被引用,因此它按原样传递。如果不加引号,它将在空格上分割为五个字符串--set
, "args={/bin/bash,-c,cd
, /var/www
, &&
, sudo -u www-data bash scripts/system/update.sh}"
,并且这些字符串将作为参数传递。
看来您希望变量内的引号也被解释,这需要添加另一层 shell 解析,或者通过eval
或 运行该东西bash -c '...'
测试脚本在这里:
$ cat test.sh
#!/bin/bash
ARGS='--set "args={this, that && that}"'
./args.sh $ARGS
eval "./args.sh $ARGS"
印刷:
<!-- language: lang-none -->
$ bash test.sh
5 args: <--set> <"args={this,> <that> <&&> <that}">
2 args: <--set> <args={this, that && that}>
(脚本args.sh
打印的数字是不同参数的数量,参数本身打印在<...>
)
请注意,它将eval
执行例如任何命令替换,因此它会打开任意代码执行。通常,最好将论点放在一个贝壳阵列相反,但在这里您将它们从一个脚本传递到另一个脚本,因此效果不太好。请参阅“如何将命令存储在变量中?”部分。在这个关于处理空白的答案。
还Bash 指南中的分词,您还可以使用set -x
它来查看 shell 实际运行的命令。