를 읽은 후 24.2. 지역 변수 , 키워드 local
로 변수 var
를 선언하면 var
“의 값은 함수의 중괄호로 구분 된 코드 블록 내에서만 액세스 할 수있었습니다.
그러나 다음 예제를 실행 한 후 는 해당 코드 블록에 의해 호출 된 함수에서 액세스하고 읽고 쓸 수 있습니다. 즉, var
가 선언 된 경우에도 local
에서 outerFunc
로, innerFunc
는 여전히이를 읽고 값을 변경할 수 있습니다.
#!/usr/bin/env bash function innerFunc() { var="new value" echo "innerFunc: [var:${var}]" } function outerFunc() { local var="initial value" echo "outerFunc: before innerFunc: [var:${var}]" innerFunc echo "outerFunc: after innerFunc: [var:${var}]" } echo "global: before outerFunc: [var:${var}]" outerFunc echo "global: after outerFunc: [var:${var}]"
출력 :
global: before outerFunc: [var:] # as expected, `var` is not accessible outside of `outerFunc` outerFunc: before innerFunc: [var:initial value] innerFunc: [var:new value] # `innerFunc` has access to `var` ?? outerFunc: after innerFunc: [var:new value] # the modification of `var` by `innerFunc` is visible to `outerFunc` ?? global: after outerFunc: [var:]
Q : 내 셸 (bash 4.3.42, Ubuntu 16.04, 64 비트)의 버그입니까, 아니면 예상되는 동작입니까?
수정 : 해결되었습니다. @MarkPlotnick이 언급했듯이 이것은 실제로 예상되는 동작입니다.
댓글
답변
셸 변수에는 동적 범위 . 변수가 함수에 대해 로컬로 선언되면 다른 함수를 호출하는 동안을 포함하여 함수가 반환 될 때까지 해당 범위가 유지됩니다.
두 가지 예외가 있습니다.
-
ksh93에서 함수가 표준
function_name () { … }
구문으로 정의 된 경우 해당 지역 변수는 동적 범위 지정을 따릅니다. 그러나 함수가 ksh 구문function function_name { … }
로 정의 된 경우 해당 지역 변수는 어휘 / 정적 범위 지정을 따르므로 이것에 의해 호출되는 다른 함수에서는 보이지 않습니다. -
zsh
의zsh/private
자동로드 가능한 플러그인은private
키워드 / 내장 : 정적 범위로 변수를 선언하는 데 사용할 수 있습니다.
ash, bash, pdksh 및 파생어, bosh에는 동적 범위 만 있습니다.
주석
- 셸의 모든 변수에 동적 범위가 있습니까? 아니면
local
로 선언 된 변수에만 적용됩니까? - @HaroldFischer 모든 변수에는 동적 범위가 있습니다.
typeset
또는declare
또는local
선언을 사용할 경우 범위는 함수가 반환 될 때까지입니다. 이러한 선언이 없으면 범위는 전역입니다. - IMHO,
If a variable is declared as local to a function, that scope remains until the function returns.
는 동적 범위 대 어휘 범위를 설명하기에 충분하지 않습니다. 설명 만 어휘 범위에도 적용됩니다. - @jinbeomhong 아니요, 어휘 범위를 사용하면이 함수가 다른 함수를 호출하는 동안 함수의 변수가 보이지 않습니다. '이 내용을 명시 적으로 설명하는 문장을 추가했습니다.
- 이것은 내장 함수를 호출하는 함수에도 영향을 줍니까? 아니면 내장 기능에 자체 범위가 있나요?
답변
버그가 아닙니다. 컨텍스트 내부의 호출입니다. outerFunc의 $ var의 로컬 복사본을 사용합니다. outerFunc의 “local”은 전역이 변경되지 않음을 의미합니다. outerFunc 외부에서 innerFunc를 호출하면 전역 $ var에는 변경되지만 outerFunc의 로컬 $ var는 변경되지 않습니다. innerFunc에 “local”을 추가하면 outerFunc의 $ var “는 변경되지 않습니다. -본질적으로 그 중 3 개가 있습니다.
- $ global :: var
- $ outerFunc :: var
- $ innerFunc :: var
Perl의 네임 스페이스 형식을 사용합니다.
답변
function innerFunc()
에서 var="new value"
는 local 으로 선언되지 않았으므로 가시 범위에서 사용할 수 있습니다 (한 번 함수가 호출되었습니다).
반대로 function outerFunc()
에서 local var="initial value"
는 local 따라서 전역 범위에서 사용할 수 없습니다 (함수가 호출 된 경우에도).
innerFunc()
가 다음의 하위 항목으로 호출 되었기 때문입니다. outerFunc()
, var는 outerFunc()
의 로컬 범위 내에 있습니다.
man 1 bash
은
local [option] [name [= value] …]
각 인수에 대해 로컬 name이라는 변수가 생성되고 값이 할당됩니다. 옵션은 선언에 의해 허용되는 모든 옵션 일 수 있습니다.함수 내에서 local이 사용되면 변수 이름이 해당 함수와 그 자식으로 제한된 가시 범위를 갖습니다. …
설명에서 예상되는 묵시적 동작은 다음에서 local var="new value
를 선언하여 달성 할 수 있습니다. function innerFunc()
.
다른 사람들이 언급했듯이 이것은 bash 셸의 버그가 아닙니다. 모든 것이 정상적으로 작동합니다.
의견
- 첫 번째 진술이 사용자에게 표시되는 내용과 모순됩니다.
innerFunc
에서outFunc
까지 호출 한 후 전역 범위에서var
의 값을 인쇄하면new value
를 인쇄하지 마십시오.
답변
로컬 범위를 강제하는 함수 :
sh_local() { eval "$(set)" command eval "\"\$@\"" }
예 :
x() { z="new value" printf "function x, z = [%s]\n" "$z" } y() { z="initial value" printf "function y before x, z = [%s]\n" "$z" sh_local x printf "function y after x, z = [%s]\n" "$z" } printf "global before y, z = [%s]\n" "$z" y printf "global after y, z = [%s]\n" "$z"
결과 :
global before y, z = [] function y before x, z = [initial value] function x, z = [new value] function y after x, z = [initial value] global after y, z = [initial value]
var
의 값이 비어 있다고 생각하는 유일한 사람은 ' 이상합니까?var
는innerFunc
에 전역 적으로 설정되어 있는데 왜 ' 끝까지 고정되지 않습니다.