${!var_name+x}를 대체한다는 것은 무엇을 의미합니까?

${!var_name+x}를 대체한다는 것은 무엇을 의미합니까?

변수가 설정되었는지 확인하는 기능이 있는 스크립트를 찾았지만 잘 이해가 되지 않습니다.

check_if_variable_is_set() {
    var_name=$1
    if [ -z "${!var_name+x}" ]; then
        false
    else
        true
    fi
}

이번 교체로 정확히 무슨 일이 일어날까요?

답변1

bash쉘 에서는 ${!var}변수 간접 주소 지정입니다. 에 이름이 있는 변수의 값으로 확장됩니다 $var.

변수 확장 ${var+value}POSIX 확장value변수가 설정된 경우 var(해당 값이 비어 있는지 여부에 관계없이) 확장됩니다 .

이를 결합하면 이름이 저장된 변수가 ${!var+x}설정되는지 여부가 확장됩니다.x$var

예:

$ foo=hello
$ var=foo
$ echo "${!var+$var is set, its value is ${!var}}"
foo is set, its value is hello
$ unset foo
$ echo "${!var+$var is set, its value is ${!var}}"

(출력으로 빈 줄)


문제의 기능은 다음과 같이 단축 될 수 있습니다.

check_if_variable_is_set () { [ -n "${!1+x}" ]; }

심지어:

check_if_variable_is_set () { [ -v "$1" ]; }

심지어:

check_if_variable_is_set()[[ -v $1 ]]

변수 이름에 대한 테스트는 어디에 -v있습니까 ? 명명된 변수가 설정되어 있으면 true이고, 그렇지 않으면 false입니다.bash


POSIXly에서는 다음과 같이 작성할 수 있습니다.

check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }

함수의 매개 변수가 공격자의 제어 하에 들어갈 수 있는 경우 이 모든 것은 잠재적인 명령 주입 취약점이라는 점에 유의하세요. 예를 들어 check_if_variable_is_set 'a[$(id>&2)]'.

이를 방지하려면 먼저 인수가 유효한 변수 이름인지 확인하는 것이 좋습니다. 변수의 경우:

check_if_variable_is_set() {
  case $1 in
    ("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
    (*)  eval '[ -n "${'"$1"'+x}" ]'
  esac
}

( [[:alpha:]]알파벳 문자는 확인됩니다.당신의 지역에서일부 쉘은 변수의 이식 가능한 문자 세트에서 알파벳 문자만 허용합니다.

관련 정보