Bash 检查字符串是否作为变量存在

Bash check if string exists as variable

我需要能够检查是否在 bash 中设置了各种类似的变量。

我需要检查变量CONFIG_STRING_TO_CHECK中定义的字符串是否已经设置。

我想做这样的事情:

#!/bin/bash

CUSTOM_PREFIX='custom1'

# Common Variable Name Endings:
CONFIG_STRINGS=( "config1" "config2" )

# Loop over common variable endings
for CONFIG_STRING in "${CONFIG_STRINGS[@]}" do :

  # Set the variable name to check
  CONFIG_STRING_TO_CHECK="${CUSTOM_PREFIX}_$CONFIG_STRING"

  # Check if variable is defined
  if [ -z ${CONFIG_STRING_TO_CHECK+x} ]; then
    echo "$CONFIG_STRING_TO_CHECK is declared";
  else
    echo "$CONFIG_STRING_TO_CHECK is not declared"; 
    exit 1;
  fi

done

谷歌搜索后我找到了 this answer,但它不起作用。我认为这是因为这是在检查变量 CONFIG_STRING_TO_CHECK 是否已设置...它始终是。

明确一点,我想检查是否设置了以下字符串:

custom1_config1
custom1_config2

不是:

CONFIG_STRING_TO_CHECK

我希望这是有道理的。请帮忙。

使用间接扩展(!),如下:

~> A=a
~> B=b
~> a_b=c
~> A_B=${A}_${B}
~> echo ${!A_B}
c

请注意,您必须有一个中间变量名称才能执行此操作——您不能这样做 echo ${!${A}_${B}}。有关详细信息,请参阅 man bash

If the first character of parameter is an exclamation point (!), it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion. The exceptions to this are the expansions of ${!prefix*} and ${!name[@]} described below. The exclamation point must immediately follow the left brace in order to introduce indirection.


编辑:我刚试过这个,它似乎有效:

# !/bin/bash

CUSTOM_PREFIX='custom1'

custom1_config1="hi"
#custom1_config2="there"

# Common Variable Name Endings:
CONFIG_STRINGS=( "config1" "config2" )

# Loop over common variable endings
for CONFIG_STRING in "${CONFIG_STRINGS[@]}"; do
        CONFIG_STRING_TO_CHECK="${CUSTOM_PREFIX}_${CONFIG_STRING}"
        if [ -z ${!CONFIG_STRING_TO_CHECK} ]; then
                echo ${CONFIG_STRING_TO_CHECK} is not defined
        else
                echo ${CONFIG_STRING_TO_CHECK} is ${!CONFIG_STRING_TO_CHECK}
        fi
done

并得到:

~/tmp/tst3> ./tmp.sh  
custom1_config1 is hi
custom1_config2 is not defined

declare 内置函数可以使用 -p 选项向您显示。

$ var=PATH
$ if declare -p "$var" &>/dev/null; then echo "$var is declared"; fi
PATH is declared
$ var=FOOBAR
$ if declare -p "$var" &>/dev/null; then echo "$var is declared"; else echo "$var is not declared"; fi
FOOBAR is not declared

另外,这个可以封装成一个函数:

$ is_declared() { declare -p "" &>/dev/null; }
$ if is_declared PATH; then echo OK; else echo NO; fi
OK
$ is_declared FOOBAR && echo OK || echo NO
NO

它也适用于局部声明给函数的变量

$ test_func() { local localvar=42; is_declared localvar && echo OK || echo NO; }
$ test_func
OK