읽고 나서24.2. 지역변수var
, 키워드를 사용하여 변수를 선언한다는 것은 함수의 중괄호로 구분된 코드 블록 내에서만 해당 값에 액세스할 수 있다는 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이 지적했듯이 이는 실제로 예상되는 동작입니다.
답변1
쉘 변수에는다이내믹 레인지. 변수가 함수에 대해 로컬로 선언되면 해당 범위는 함수가 반환될 때까지 유효하게 유지됩니다.다른 함수를 호출하는 동안 포함!
이는 대부분의 프로그래밍 언어와 뚜렷한 대조를 이룹니다.어휘 범위. Perl에는 다음 두 가지가 모두 있습니다.my
어휘 범위의 경우,local
또는 동적 범위가 없는 선언입니다.
두 가지 예외가 있습니다.
ksh93에서 표준 구문을 사용하여 함수를 정의하면
function_name () { … }
해당 지역 변수는 동적 범위 지정을 따릅니다. 그러나 함수가 ksh 구문을 사용하여 정의된 경우function function_name { … }
해당 지역 변수는 어휘/정적 범위를 따르므로 호출된 다른 함수에서는 표시되지 않습니다.zsh/private
자동 로딩 플러그인은 정적 범위로 변수를 선언하는 데 사용할 수 있는 키워드/내장 함수를 제공zsh
합니다private
.
ash, bash, pdksh 및 그 파생물인 bosh에는 동적 범위만 있습니다.
답변2
function innerFunc()
그 안에 var='new value'
다음과 같이 선언했습니다.현지의이므로 가시 범위(함수 호출 후)에서 사용할 수 있습니다.
대신 선언 function outerFunc()
에서 다음과 같이local var='initial value'
현지의, 따라서 함수가 호출된 경우에도 전역적으로 사용할 수 없습니다.
var는 innerFunc()
의 하위 항목으로 호출되므로 outerFunc()
의 로컬 범위에 속합니다 outerFunc()
.
man 1 bash
명확히 하는 데 도움이 될 수 있음
지역[옵션][이름[=값] ...]
각 매개변수에 대해 name이라는 지역 변수가 생성되고 값이 할당됩니다. 옵션은 허용 가능하다고 선언된 모든 옵션이 될 수 있습니다. 함수 내에서 로컬을 사용하면 변수 이름이 해당 함수와 해당 하위 함수에만 표시됩니다. ...
설명에서 예상되는 암시적 동작은 local var='new value
에서 선언하여 달성할 수 있습니다 function innerFunc()
.
다른 사람들이 말했듯이 이것은 bash 쉘의 버그가 아닙니다. 모든 것이 예상대로 작동합니다.
답변3
이것은 버그가 아닙니다. externalFunc 컨텍스트의 호출은 $var의 로컬 복사본을 사용합니다. OuterFunc의 "local"은 전역이 변경되지 않음을 의미합니다. externalFunc 외부에서 innerFunc를 호출하면 전역 $var는 변경되지만 externalFunc의 로컬 $var는 변경되지 않습니다. innerFunc에 "local"을 추가하면 externalFunc의 $var는 변경되지 않습니다. 기본적으로 3개가 됩니다.
- $global::var
- $outerFunc::var
- $innerFunc::var
일종의 Perl의 네임스페이스 형식을 사용합니다.
답변4
이는 예상된 동작입니다. 지역 변수에는 동적 범위가 있습니다. 변수는 선언된 함수가 반환될 때까지 범위 내에 유지됩니다. 따라서 이러한 변수는 이 함수에서 호출되는 모든 함수의 범위에 포함됩니다.
함수가 다른(로컬 또는 전역) 변수와 동일한 이름을 가진 새 로컬 변수를 선언하는 경우 새 로컬 변수는 별도의 메모리 영역에 상주하며 동일한 이름을 가진 다른 변수와 다른 값을 보유할 수 있습니다.
함수 내에서 로컬 선언이 나타나는 위치는 중요하지 않습니다.
예제로 제공된 코드를 약간 수정했습니다.
#!/usr/bin/env bash
function innerFunc() {
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}]"
innerFunc
echo "global: after outerFunc: [var:${var}]"