이 질문 의 배경 부분에 대한 후속 조치 .
에서 이중 치환에 bash
사용할 수 있습니다 . 둘 다, 구식 (hack-y)이 작동합니다.${!FOO}
zsh
${(P)FOO}
eval \$$FOO
따라서 나에게 가장 똑똑하고 가장 논리적 인 것은 ${${FOO}}, ${${${FOO}}}…
이중 / 삼중 / n 대체입니다. 왜 이것이 예상대로 작동하지 않습니까?
두 번째로 다음은 무엇 않습니다 \
에서 할 eval
문? 나는 그것이 탈출이라고 생각하여 eval \$$$FOO
불가능한 것을 만듭니다 . 모든 쉘에서 작동하는 트리플 / n 대체 방법?
답변
은 \
확대 방지하기 위해 사용되어야한다 $$
(현재의 프로세스 ID). 삼중 치환의 경우 이중 평가가 필요하므로 각 평가에서 원하지 않는 확장을 피하기 위해 더 많은 이스케이프가 필요합니다.
#! /bin/bash
l0=value
l1=l0
l2=l1
l3=l2
l4=l3
echo $l0
eval echo \$$l1
eval eval echo \\$\$$l2
eval eval eval echo \\\\$\\$\$$l3
eval eval eval eval echo \\\\\\\\$\\\\$\\$\$$l4
답변
#!/bin/bash
hello=world
echo=hello
echo $echo ${!echo}
답변
의 값이 FOO
유효한 변수 이름 (예 🙂 BAR
이고 eval \$$FOO
값 BAR
을 별도의 단어로 나누고 각 단어를 와일드 카드 패턴으로 취급하며 결과의 첫 번째 단어를 명령으로 실행하고 다른 단어를 인수로 전달합니다. 달러 앞의 백 슬래시는 문자 그대로 처리되므로 eval
내장 문자에 전달되는 인수 는 4 자 문자열 $BAR
입니다.
${${FOO}}
구문 오류입니다. 일반적인 쉘에는 이러한 기능이 없기 때문에 “이중 대체”를 수행하지 않습니다 (어쨌든이 구문을 사용하지 않음). zsh을에서 ${${FOO}}
이다 유효하고 이중 대체이지만, 그것은 당신이 원하는 것과 다르게 동작 : 그것의 가치에 두 개의 연속 변환을 수행 FOO
, 신원 변환되어 둘을, 그래서 글을 쓰는 단지 멋진 방법입니다 ${FOO}
.
변수의 값을 변수로 취급하려면 올바르게 인용하도록주의하십시오. 결과를 변수로 설정하면 훨씬 쉽습니다.
eval "value=\${$FOO}"
답변
{ba,z}sh
해결책
다음은 둘 다에서 작동하는 함수입니다 {ba,z}sh
. POSIX 와도 호환됩니다.
인용에 화를 내지 않고 다음과 같이 여러 수준의 간접적으로 사용할 수 있습니다.
$ a=b
$ b=c
$ c=d
$ echo $(var_expand $(var_expand $a)
d
또는 더 많은 (!?!) 간접 레벨이있는 경우 루프를 사용할 수 있습니다.
주어진 경우 경고합니다 :
- 널 입력
- 설정되지 않은 변수 이름
# 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 [ -z "${1-}" ] || [ $# -ne 1 ]; then
printf 'var_expand: expected one argument\n' >&2;
return 1;
fi
eval printf '%s' "\"\${$1?}\""
}
답변
마찬가지로이 ${$foo}
의 장소에서 작동하지 않습니다 ${(P)foo}
에 zsh
, 어느 쪽도 않습니다 ${${$foo}}
. 각 간접 레벨을 지정하면됩니다.
$ foo=bar
$ bar=baz
$ baz=3
$ echo $foo
bar
$ echo ${(P)foo}
baz
$ echo ${(P)${(P)foo}}
3
물론 중첩 대체를 허용하지 않기 때문에 ${!${!foo}}
에서 작동 하지 않습니다.bash
bash
답변
왜 그렇게해야합니까?
항상 다음과 같은 여러 단계로 수행 할 수 있습니다.
eval "l1=\${$var}"
eval "l2=\${$l1}"
...
또는 다음과 같은 기능을 사용하십시오.
deref() {
if [ "$1" -le 0 ]; then
eval "$3=\$2"
else
eval "deref $(($1 - 1)) \"\${$2}\" \"\$3\""
fi
}
그때:
$ a=b b=c c=d d=e e=blah
$ deref 3 a res; echo "$res"
d
$ deref 5 a res; echo "$res"
blah
FWIW zsh
:
$ echo ${(P)${(P)${(P)${(P)a}}}}
blah
답변
POSIX 솔루션
인용에 화를 내지 않고이 기능을 다음과 같이 여러 수준의 간접적으로 사용할 수 있습니다.
$ a=b
$ b=c
$ c=d
$ echo $(var_expand $(var_expand $a)
d
또는 더 많은 (!?!) 간접 레벨이있는 경우 루프를 사용할 수 있습니다.
주어진 경우 경고합니다 :
- 널 입력
- 하나 이상의 논쟁
- 설정되지 않은 변수 이름
# Expand the variable named by $1 into its value. Works in both {ba,z}sh
# eg: a=HOME $(var_expand $a) == /home/me
function var_expand {
if [ "$#" -ne 1 ] || [ -z "${1-}" ]; then
printf 'var_expand: expected one argument\n' >&2;
return 1;
fi
eval printf '%s' "\"\${$1?}\""
}