bash zsh에서 ${!FOO}에 대한 간접 참조와 동일한 것은 무엇입니까?

bash zsh에서 ${!FOO}에 대한 간접 참조와 동일한 것은 무엇입니까?

${!FOO}에서 이중 대체를 수행합니다 bash. 즉, FOO의 (문자열) 값을 가져와 변수 이름으로 사용한다는 의미입니다.
zsh이 기능은 지원되지 않습니다.

bash이 작업을 및 에서 동일하게 만드는 방법이 있습니까 zsh?

배경:

다음과 같은 환경 변수 목록이 있습니다.

PATH MAIL EDITOR

변수 이름을 먼저 인쇄한 다음 해당 값을 인쇄하려고 합니다.

이것은 작동 bash하지만 다음의 경우에는 작동하지 않습니다 zsh.

for VAR in LIST
do
        echo $VAR
        echo ${!VAR}
done

아마도 어떤 면에서는 "오래된 방식"이어야 eval하지만 제대로 작동하도록 할 수는 없습니다.

for VAR in LIST
do
        echo $VAR
        echo `eval \$$VAR`
done

나는 왜 임의의 깊은 교체를 수행할 수 없는지 또는 필요한 ${${VAR}}경우에도 결코 이해하지 못할 것이므로 그에 대한 설명이 좋을 것입니다.${${${VAR}}}

답변1

원래 질문에 대한 Profpatsch의 의견은 ${(p)FOO}간접 변수 참조의 내용을 출력하는 예를 제공합니다. 로고가 올바르지 않거나 철자가 틀렸습니다. 소문자 p 대신 대문자 P를 사용해야 합니다. 사용: ${(P)FOO}.

다음은 원하는 출력을 생성해야 합니다.

#! /bin/zsh
LIST=(PATH MAIL EDITOR)
for VAR in ${LIST}
do
    print -r -- "${VAR}:  ${(P)VAR}"
done

~에서zshexpn맨 페이지 섹션 -매개변수 확장 플래그:

  This forces the value of the parameter name to be interpreted as a further
  parameter name,  whose  value  will  be used where appropriate.  Note that
  flags set with one of the typeset family of commands (in particular case
  trans‐formations) are not applied to the value of name used in this fashion.

  If used with a nested parameter or command substitution, the result of that
  will be taken as a parameter  name  in the  same  way.   For  example,  if
  you  have  `foo=bar'  and `bar=baz', the strings ${(P)foo}, ${(P)${foo}}, and
  ${(P)$(echo bar)} will be expanded to `baz'

어느 시점에서 기대한 결과가 나오지 않는 이유를 읽었 ${${${VAR}}}지만 지금은 찾을 수 없습니다. 다음을 수행할 수 있습니다.

first="second" ; second="third" ; third="fourth" ; fourth="fifth"
print -r -- ${(P)${(P)${(P)first}}}
fifth

답변2

bash와 zsh 모두 간접 확장을 수행하는 방법이 있지만 서로 다른 구문을 사용합니다.

; 을 사용하면 간접 확장을 쉽게 수행할 수 있습니다 eval. 이는 모든 POSIX 및 대부분의 Bourne 쉘에서 작동합니다. 값에 셸에서 특별한 의미를 갖는 문자가 포함되어 있는 경우 올바르게 인용해야 합니다.

eval "value=\"\${$VAR}\""
echo "$VAR"
echo "$value"

${${VAR}}어떤 쉘에서도 구현된 기능이 아니기 때문에 작동하지 않습니다. 중괄호 안의 내용은 제외 구문 규칙을 준수해야 합니다 ${VAR}. (zsh에서 이는 지원되는 구문이지만 다른 작업을 수행합니다. 중첩 대체는 동일한 값에 대해 연속 변환을 수행합니다. 값 쌍에 대해 두 개의 ID 변환을 수행하는 ${${VAR}}것과 같습니다 .)$VAR

답변3

평가판을 올바르게 사용하고 있지 않습니다. 귀하의 예에서는 "$"(예: "$VALUE")가 앞에 있는 $VAR 값이 명령으로 실행됩니다. 그것은 당신이 원하는 것이 아닙니다. 다른 변수에서 이름을 가져온 변수의 확장을 계산하려고 합니다.

$ for i in `echo PATH MAIL EDITOR`; 
    do eval moo="\${$i}" 
    echo $moo 
done
/usr/local/sbin:/usr/local/bin:/usr/sbin:/u (...)
/var/mail/root
nano

답변4

{ba,z}sh해결책

이는 {ba,z}sh에서 유효한 함수입니다. 나는 그것이 POSIX와도 호환된다고 믿습니다.

다음 메시지가 표시되면 경고가 표시됩니다.

  • 빈 입력
  • 하나 이상의 인수
  • 설정되지 않은 변수 이름
# Expand the variable named by $1 into its value. Works in both {ba,z}sh
# eg: a=HOME $(var_expand $a) == /home/me
var_expand() {
  if [ "$#" -ne 1 ] || [ -z "${1-}" ]; then
    printf 'var_expand: expected one non-empty argument\n' >&2;
    return 1;
  fi
  eval printf '%s' "\"\${$1?}\""
}

관련 정보