zsh: 변수를 참조로 전달하고 해당 값을 수정합니까(예: bash의 local -n namerefs)?

zsh: 변수를 참조로 전달하고 해당 값을 수정합니까(예: bash의 local -n namerefs)?

eval을 사용하지 않고 변수를 zsh 함수에 전달하고 해당 값을 수정할 수 있습니까? 나는 이것을 수행하는 bash 방법을 발견했습니다 local -n. ::https://stackoverflow.com/a/50281697

답변1

typeset -n실제로 원래 ksh93(1993)에서 나왔습니다. 2014년에 출시된 bash 4.3에도 비슷한 내용이 추가되었습니다. ksh93에서는 bash/zsh의 동적 범위 지정(함수가 항상 호출자 로컬 변수 1을 보는 경우)과 달리 ksh93이 정적 범위 지정(내보내지 않으면 호출자에서 로컬 변수에 액세스할 수 없음)을 수행하기 때문에 더 유용합니다. 또한보십시오:

$ bash -c 'function f { typeset -n var=$1; var=x;}; var=0; f var; echo "$var"'
environment: line 0: typeset: warning: var: circular name reference
environment: warning: var: circular name reference
environment: warning: var: circular name reference
x
$ ksh -c 'function f { typeset -n var=$1; var=x;}; var=0; f var; echo "$var"'
x

zsh에는 확장 및 할당을 위한 변수 역참조 연산자가 있지만 nameref를 지원하지 않습니다.

$ expand() print -r -- ${(P)1}
$ assign() : ${(P)1::=$2}
$ var=foo
$ expand var
foo
$ assign var bar
$ print -r -- $var
bar

eval또는 언제든지 Bourne과 유사한 쉘에서 작동하는 표준 방법을 사용할 수 있습니다 .

expand() {
  eval 'printf "%s\n" "${'"$1"'}"'
}
assign() {
  eval "$1=\$2"
}

물어보기 전에 아니요 P. 여기서처럼 올바르게 수행된다면 bash에서 플래그나 이름 참조를 사용하는 것보다 더 안전하지 않습니다. 어떤 방법을 사용하든 중요한 것은이름변수의 값이 적절하게 제어됩니다.

assign var "$external_input"nameref를 사용하든 사용하지 않든 assign "$external_input" value안전합니다. 또는 which와 동일하며 bash/ksh/zsh의 임의 명령 실행 취약점입니다.expand "$external_input"Peval[ -v "$external_input" ]read "$external_input"

당신은 또한 볼 수 있습니다zsh-workers 메일링 리스트에 대한 토론다양한 간접배분 방법의 장점에 대해 설명합니다.

그 다음에2001년 토론ksh93 스타일 nameref 지원을 zsh에 추가하는 것을 고려하고 있습니다. 그리고2015년에 다시그리고2023년, 이는 해당 기능을 추가하는 데 관심이 있으며 5.10이든 6.0이든 결국 5.9 이후 다음 버전에 추가될 수 있음을 나타냅니다.


1 함수 전용으로 만들려면 zsh/param/private모듈의 변수를 참조하세요 .zsh

관련 정보