使用函数检查bash环境变量是否存在

5

这个问题可能已经在其他的SO帖子中有了答案,但我不认为我能找到完全符合我的要求的答案。

我有一个(#!/usr/bin/env bash)函数,它检查(环境)变量是否存在。

checkForVariable() {
  if [[ -z $1 ]]; then
    echo "Error: Define $1 environment variable"
    exit 1
  fi
}

但在错误消息中,我希望它告诉我缺少哪个环境变量。
如果我使用以下命令进行调用:
checkForVariable "${ENVIRONMENT_NAME}"
如果 ENVIRONMENT_NAME 没有设置,那么显然我会得到 "Error: Define environment variable",这并不有用。
如何更改我的函数,以便我可以向 checkForVariable 传递一个字符串而不是一个变量引用,即
checkForVariable "ENVIRONMENT_NAME"
我尝试过例如 if [[ -z "\$${1}" ]]; then 和 if [[ -z "${$1}" ]]; then,但这些方法都无法工作。
3个回答

5
您可以使用此函数:
checkForVariable() {
    if [[ -z ${!1+set} ]]; then
       echo "Error: Define $1 environment variable"
       exit 1
    fi
}

然后使用它:

checkForVariable ENVIRONMENT_NAME

请注意,${!1+set}将在您的函数中使用给定名称解引用变量$1:+set检查是必需的,以检查环境变量是否设置为空值。 代码演示

由于某些原因,这对我来说不起作用。定义一个变量消息总是被回显。我正在运行MacOS。 - Maroun
就是这样。我用 myvar=bla 设置了它。 - Maroun
1
我会这样测试它:[[ "$(declare -p "$1")" =~ ^declare\ -x ]]。 这实际上测试的是参数1中的变量名是否为导出的环境变量,而不是简单的全局变量。 - Léa Gris
@LéaGris,我已经使用你的测试更新了我的答案。 - Jetchisel
2
如果您的 bash 版本支持它(我相信是4.4或更高版本),您也可以使用 [[ ${!1@a} = *x* ]]。 (${...@a} 运算符扩展为变量属性,而不是其值。)需要间接扩展来从 $1 获取名称,而不是检查 $1 的属性。 - chepner
显示剩余5条评论

3
您可以使用-v并使用!进行否定,以及测试-x属性而不是-z
checkForVariable() {
  local env_var=
  env_var=$(declare -p "$1")
  if !  [[ -v $1 && $env_var =~ ^declare\ -x ]]; then
    echo "Error: Define $1 environment variable"
    exit 1
  fi
}

那么,您可以在脚本内完成测试。

checkForVariable ENVIRONMENT_NAME

这是根据测试需求而来的。

help test | grep -- '^[[:space:]]*-v'

输出

-v VAR         True if the shell variable VAR is set.

还有那个 !

help test | grep -- '^[[:space:]]*!'

输出

! EXPR         True if expr is false.

同样针对环境变量,正如chepner所指出的,需要通过测试declare -p ENV_NAME的输出来查找-x属性。
help declare | grep -- '^[[:space:]]*-x'

输出

-x        to make NAMEs export

尽管上述方法在脚本内部测试变量时有效,但如果您想在交互式会话中执行此操作,则需要对文件/脚本进行源操作。
将其放入您的dotfiles/rcfiles中,例如~/.profile或~/.bash_profile或~/.bashrc。
checkForVariable() {
  local env_var=
  env_var=$(declare -p "$1")
   if ! [[  -v $1 && $env_var =~ ^declare\ -x ]]; then
     echo "Error: Define $1 environment variable"
     return 1
   fi
 }

只需要将exit替换为return,否则交互会话将立即退出。

然后再源化该rc文件。

source ~/.profile 

假设函数位于~/.profile文件中。在交互式会话期间,您可以进行测试。
checkForVariable ENVIRONMENT_NAME

编辑:如chepner所指出的,我已经添加了-x属性的测试。


3
这不能区分常规的shell变量和环境变量。你还需要检查名称上是否有"-x"属性。 - chepner
@chepner,感谢您指出这一点,我已经更新了我的帖子。 - Jetchisel

0

由于您在shebang中有env,因此可以执行以下操作:

printenv | grep "^ENV_VARIABLE"

或者你可以使用set:

set | grep -E "^ENV_VARIABLE=.+$"

还有一些Python的单行代码:

python3 -c 'import os; import sys; print(bool(os.getenv(sys.argv[1])))'  HOME

当然,您可以以其他方式检查printenv的结果:

[ ! -z `printenv VAR` ] || echo "VAR not exists"

所以在你的函数中变成

function checkEnv() { [ ! -z `printenv $1` ] || echo "$1 Error message.."; }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接