쉘 함수에서 지역 변수의 범위 즉,이 비록 var선언 local에 outerFunc, innerFunc여전히 그것을

24.2를 읽은 후 . 지역 변수는 , 내가 변수 선언 생각 var키워드가 local의미하는 것을 var의 값이 함수의 중괄호로 구분 코드 블록 내에서만 액세스 할 수있었습니다.

그러나 다음 예제를 실행 한 후, 나는 그가 발견 var도 읽고, 액세스 코드의 블록에 의해 호출 기능에서 쓸 수 있습니다 – 즉,이 비록 var선언 localouterFunc, innerFunc여전히 그것을 읽고 그 값을 변경 할 수 있습니다.

Run It Online

#!/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. ksh93에서 함수가 표준 function_name () { … }구문으로 정의되면 로컬 변수는 동적 범위를 따릅니다. 그러나 함수가 ksh 구문으로 정의 된 경우 function function_name { … }로컬 변수는 어휘 / 정적 범위를 준수하므로이 함수는 다른 함수에서 볼 수 없습니다.

  2. zsh/private에 autoloadable 플러그인 zsh으로 제공하는 private키워드 / 내장 정적 범위의 변수를 선언하는 데 사용될 수있다.

ash, bash, pdksh 및 파생 상품, bosh에는 동적 범위 만 있습니다.


답변

버그가 아닙니다. outerFunc 컨텍스트 내부의 호출은 해당 로컬 $ var 복사본을 사용합니다. outerFunc의 “local”은 전역이 변경되지 않았 음을 의미합니다. outerFunc 외부에서 innerFunc를 호출하면 글로벌 $ var가 변경되지만 outerFunc의 로컬 $ var은 변경되지 않습니다. innerFunc에 “local”을 추가하면 outerFunc의 $ var는 변경되지 않습니다. 본질적으로 3 개가 있습니다.

  • $ global :: var
  • $ outFunc :: var
  • $ innerFunc :: var

Perl의 네임 스페이스 형식을 사용하려면


답변

함수를 사용하여 로컬 범위를 강제 할 수 있습니다.

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]

출처


답변

에서 function innerFunc()var='new value'선언되지 않은 지역 , 그러므로 (함수가 호출 된 후) 눈에 보이는 범위에서 사용할 수 있습니다.

에 반대로, function outerFunc()local var='initial value'선언 된 지역 , 그러므로 (함수가 호출 된 경우에도) 전역에서 사용할 수 없습니다.

innerFunc()의 하위 항목으로 호출 되었으므로 outerFunc()var의 로컬 범위 내에 outerFunc()있습니다.

man 1 bash 명확히하는 데 도움이 될 수 있습니다

로컬 [옵션] [이름 [= 값] …]

각 인수에 대해 name이라는 로컬 변수가 작성되고 값이 지정됩니다. 옵션은 선언에 의해 허용되는 옵션 중 하나 일 수 있습니다. 함수 내에서 local을 사용하면 변수 이름에 해당 함수와 해당 하위로 제한된 가시적 범위가 있습니다. …

설명에서 예상되는 암시적인 동작은에서 선언 local var='new value하여 얻을 수 있습니다 function innerFunc().

다른 사람들이 말했듯이, 이것은 bash 쉘의 버그가 아닙니다. 모든 것이 제대로 작동합니다.


답변