仅当在调用脚本中设置了参数并且我注意到某些奇怪的行为时,我才尝试有条件地将参数传递给bash脚本。 我正在使用参数扩展来简化此操作,仅在设置了相应变量的情况下才输出选项。目的是将参数从“父”脚本传递到“子”脚本。
考虑以下示例:
调用脚本:
#!/bin/bash
# 1.sh
ONE="TEST_ONE"
TWO="TEST_TWO"
./2.sh \
--one "${ONE}" \
"${TWO:+"--two ${TWO}"}" \
--other
和被调用的脚本:
#!/bin/bash
# 2.sh
while [[ $# -gt 0 ]]; do
key="${1}"
case $key in
-o|--one)
ONE="${2}"
echo "ONE: ${ONE}"
shift
shift
;;
-t|--two)
TWO="${2}"
echo "TWO: ${TWO}"
shift
shift
;;
-f|--other)
OTHER=1
echo "OTHER: ${OTHER}"
shift
;;
*)
echo "UNRECOGNISED: ${1}"
shift
;;
esac
done
输出:
ONE: TEST_ONE
UNRECOGNISED: --two TEST_TWO
OTHER: 1
观察选项“ --two”的行为,该行为将无法识别。看起来好像已正确扩展了该字符串,但并未将其识别为两个不同的字符串。
谁能解释为什么会这样?我已经看到它写在one source中的是it will not work with positional parameter arguments
,但是我仍然不明白为什么这样做会如此。
答案 0 :(得分:3)
这是因为当您从$2
进行参数扩展而传递1.sh
时,您引用它的方式是将--two TEST_TWO
视为一个单独的参数,因此数字2.sh
中的参数的结果产生4
而不是5
但是,也就是说,将$2
用作${TWO:+--two ${TWO}}
可以解决问题,但是如果$2
的内容包含空格,则会对其进行单词分割。您需要使用数组。
作为一种更推荐和更可靠的方法,请在1.sh
上使用以下数组作为
argsList=(--one "${ONE}" ${TWO:+--two "${TWO}"} --other)
并将其传递为
./2.sh "${argsList[@]}"
或如果您熟悉引用规则的工作原理(如何以及何时引用以防止单词拆分的发生),请在命令行上直接使用它,如下所示。这样可以确保内容变量ONE
和TWO
保留,即使它们有空格。
./2.sh \
--one "${ONE}" \
${TWO:+--two "${TWO}"} \
--other
作为一些建议的准则
getopts()
进行更健壮的参数标志解析