Bash函数用于检查未设置和空白变量

时间:2015-11-17 06:37:18

标签: bash

我正在编写一个bash函数来检查空白或未设置的变量。

function exit_if_var_does_not_exist {
    TMP_NAME=$1
    TMP_VALUE=`echo $TMP_NAME`
    if [ -z ${TMP_VALUE+x} ]; then
        echo "Variable [${TMP_NAME}] is unset. Exiting."
        exit 1
    else
        if [ ${TMP_VALUE} = "" ]; then
            echo "Variable [${TMP_NAME}] is set to ''. Exiting."
            exit 1
        fi
    fi
    echo "Variable [${TMP_NAME}] is set to ${TMP_VALUE}"
}

VAR=Test
exit_if_var_does_not_exist VAR
BLANK=
exit_if_var_does_not_exist BLANK

这不会给我TMP_VALUE中的预期输出。有人可以帮我解决我在这里缺少的事情吗?

-bash-3.2$ ./x.sh
Variable [VAR] is set to VAR
Variable [BLANK] is set to BLANK

3 个答案:

答案 0 :(得分:2)

空测试块的问题在于,此片段中的任何一点都没有实际获得最初命名变量的值。

当您使用TMP_NAME=$1时,您将输入变量的名称分配给TMP_NAME,然后

TMP_VALUE=`echo $TMP_NAME`

只需将该名称指定给TMP_VALUE即可。实际上你刚刚运行了TMP_VALUE=$1

因此,您无法测试最初命名的变量是否包含此处的任何内容。

为此,您需要使用indirect expansion

TMP_VALUE=${!TMP_NAME}TMP_VALUE=${!1}

评论你的"未设置"顶部的测试块可以从不触发。

TMP_VALUE可以从不取消设置,因为您已分配给它。即使TMP_VALUE=也将变量标记为" set"。所以这一点毫无用处。虽然,并且感谢David C. Rankin尝试了足够长的时间让我想到这一点,但可以使用间接扩展技巧来实现这一目标。

对于[ -z "${!TMP_NAME+x}" ]中指定的任何set变量,

TMP_NAME将返回true,对于未设置的变量,

: "${VAR:?Error VAR is unset or blank.}" || exit 1 将返回false。

如果变量未设置或空白,那么所有人都会说你想要做的是错误。只需使用

[

最后,正如David C. Rankin在-z内部指出的那样,你需要引用当他们改变测试含义时可能会消失的扩展(你在上面的[ ${TMP_VALUE} = "" ]测试中看到这一点)以及这里。

所以[ "${TMP_VALUE}" = "" ]需要TMP_VALUE因为[ = "" ]为空,第一个版本会出现语法错误,因为test不是{{}的有效调用1}} / [

答案 1 :(得分:2)

我不确定这适用于所有情况,但请尝试:

#!/bin/bash

function exit_if_var_does_not_exist {
    local TMP_NAME=$1
    local TMP_VALUE="${!TMP_NAME}"
    [ -z "${!TMP_NAME}" ] && {
        echo "Variable [${TMP_NAME}] is unset. Exiting."
        return 1
    }
    [ "$TMP_VALUE" = "" ] && {
        echo "Variable [${TMP_NAME}] is set to ''. Exiting."
        return 1
    }
    echo "Variable [${TMP_NAME}] is set to ${TMP_VALUE}"
}

VAR=Test
exit_if_var_does_not_exist VAR
# BLANK=
exit_if_var_does_not_exist BLANK

<强>输出

$ bash tstempty.sh
Variable [VAR] is set to Test
Variable [BLANK] is unset. Exiting.

改进间接汤

在评论和建议中进行了一些讨论之后,我认为我的版本更加一致。再一次,我认为这是合格的,我不确定它是否适用于所有情况,但对于测试似乎:

#!/bin/bash

function exit_if_var_does_not_exist {
    local TMP_NAME=$1
    local TMP_VALUE="${!TMP_NAME}"
    if ! declare -p $1 >/dev/null 2>&1 ; then
        [ -z "${!TMP_NAME}" ] && {
            echo "Variable [${TMP_NAME}] is unset. Exiting."
            return 1
        }
    elif [ "$TMP_VALUE" = "" ]; then
        echo "Variable [${TMP_NAME}] is set to ''. Exiting."
        return 1
    fi
    echo "Variable [${TMP_NAME}] is set to ${TMP_VALUE}"    
}

VAR=Test
exit_if_var_does_not_exist VAR
# BLANK=
exit_if_var_does_not_exist BLANK
EMPTY=""
exit_if_var_does_not_exist EMPTY

<强>输出

$ bash tstempty.sh
Variable [VAR] is set to Test
Variable [BLANK] is unset. Exiting.
Variable [EMPTY] is set to ''. Exiting.

答案 2 :(得分:1)

另一种方式:

exit_if_var_does_not_exist() {
  if ! (set -u; : "${!1}") >/dev/null 2>&1; then
    printf 'Variable [%s] is unset. Exiting.\n' "$1"
    exit 1
  elif [ -z "${!1}" ]; then
    printf "Variable [%s] is set to ''. Exiting.\n" "$1"
    exit 1
  fi
  printf 'Variable [%s] is set to %s\n' "$1" "${!1}"
}

如果您不需要分开两个错误消息:

exit_if_var_does_not_exist() {
  : "${!1:?$1 is unset or blank}"
  printf 'Variable [%s] is set to %s\n' "$1" "${!1}"
}