程序参数中的参数扩展具有奇怪的行为

时间:2018-12-19 10:27:13

标签: linux bash shell unix parameters

仅当在调用脚本中设置了参数并且我注意到某些奇怪的行为时,我才尝试有条件地将参数传递给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,但是我仍然不明白为什么这样做会如此。

1 个答案:

答案 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[@]}"

或如果您熟悉引用规则的工作原理(如何以及何时引用以防止单词拆分的发生),请在命令行上直接使用它,如下所示。这样可以确保内容变量ONETWO保留,即使它们有空格。

./2.sh \
    --one "${ONE}" \
    ${TWO:+--two "${TWO}"} \
    --other

作为一些建议的准则

  • 对于用户定义的变量,始终使用小写的变量名,以免将它们与外壳程序本身维护的环境变量混淆。
  • 使用getopts()进行更健壮的参数标志解析