【问题标题】:How to (not) pass empty quoted variables as arguments to commands如何(不)将空引用变量作为参数传递给命令
【发布时间】:2013-11-30 23:12:00
【问题描述】:

我在 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}"
}

它可以被称为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

我使用 if/else 暂时解决了这个问题,所以 DATA_OPTIONPARAMS 根本不会通过:

    [..]

    if [ -z "${PARAMS}" ]; then
        curl -o - --data "${PARAMS}" "${URL}"
    else
        curl -o - "${URL}"
    fi
}

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

【问题讨论】:

    标签: bash shell


    【解决方案1】:

    您实际上可以在参数扩展中使用“使用替代值”选项 (:+) 彻底解决此问题:

    curl -o - ${PARAMS:+"--data" "$PARAMS"} "${URL}"
    

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

    【讨论】:

    • 为什么要引用--data,为什么不直接引用${PARAMS:+--data "$PARAMS"}
    • @janos: 两者都行,但我更喜欢引用的版本,原因有两个:首先,在编写 shell 脚本时,习惯性引用事物更安全,除非有理由不去尝试记住何时你可以不加引号就脱身。其次,当阅读这样的脚本时,如果参数扩展选项(:+)在它们之间有引号(空格也可以,但是见第一个原因)。
    【解决方案2】:

    我觉得这是懒惰和优雅的很好的结合:

    curl -o - --data "&$PARAMS" "$URL"
    

    没错,那里有一个没用的&amp;。问题是它不会伤害任何人,它很短,并且它应该适用于您的两种情况,无论您是否在 PARAMS 中有任何内容。

    【讨论】:

      猜你喜欢
      • 2016-05-31
      • 2011-02-10
      • 2021-01-03
      • 1970-01-01
      • 2015-01-21
      • 1970-01-01
      • 2020-08-19
      • 2023-02-21
      • 1970-01-01
      相关资源
      最近更新 更多