如何(不)将空引用变量作为参数传递给命令

kon*_*kos 5 bash shell

我在bash脚本中有一个函数,看起来像这样(简化):

# Usage: f URL [PARAMETER]...
f() {
    local URL="$1"; shift

    local PARAMS
    for arg in "$@"; do
        PARAMS="${PARAMS}&${arg}"
    done
    PARAMS="${PARAMS#'&'}"

    local DATA_OPTION
    [ -z "${PARAMS}" ] || DATA_OPTION='--data'

    curl -o - "${DATA_OPTION}" "${PARAMS}" "${URL}"
}
Run Code Online (Sandbox Code Playgroud)

它可以被称为f http://example.com/resourcef http://example.com/resource p1=v1 p2=v2.问题是,当DATA_OPTIONPARAMS是空的.在这种情况下,Bash将两个空参数传递给curl,然后通过curl将其识别为URL并生成以下丑陋的消息:

curl: (3) <url> malformed
curl: (3) <url> malformed
Run Code Online (Sandbox Code Playgroud)

我使用if/else暂时解决了这个问题,所以DATA_OPTION并且PARAMS根本没有传递:

    [..]

    if [ -z "${PARAMS}" ]; then
        curl -o - --data "${PARAMS}" "${URL}"
    else
        curl -o - "${URL}"
    fi
}
Run Code Online (Sandbox Code Playgroud)

但这对我来说似乎很难看.有更优雅的解决方案吗?请注意,PARAMS需要引号,因为某些参数值可能包含空格.

Gor*_*son 8

您可以使用:+参数扩展中的"使用备用值"选项()来干净地解决这个问题:

curl -o - ${PARAMS:+"--data" "$PARAMS"} "${URL}"
Run Code Online (Sandbox Code Playgroud)

如果PARAMS为空或未定义,则整个${PARAMS:+"--data" "$PARAMS"}事物计算为空字符串,并且因为它不是双引号,所以单词拆分将其完全删除.另一方面,如果PARAMS是非空的,它会被有效替换"--data" "$PARAMS",这正是你想要的.

  • @janos:两者都可以,但我更喜欢引用版本有两个原因:首先,在编写 shell 脚本时,习惯性引用内容更安全,除非有理由不这样做,而不是尝试记住什么时候可以不用引号。其次,当阅读这样的脚本时,如果它们之间有引号(空格也可以工作,但请参阅第一个原因)。 (2认同)