쉘 함수의 지역 변수 범위

를 읽은 후 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이 언급했듯이 이것은 실제로 예상되는 동작입니다.

댓글

  • 예상되는 동작입니다.
  • Am I 출력의 마지막 줄에서 var의 값이 비어 있다고 생각하는 유일한 사람은 ' 이상합니까? varinnerFunc에 전역 적으로 설정되어 있는데 왜 ' 끝까지 고정되지 않습니다.

답변

셸 변수에는 동적 범위 . 변수가 함수에 대해 로컬로 선언되면 다른 함수를 호출하는 동안을 포함하여 함수가 반환 될 때까지 해당 범위가 유지됩니다.

두 가지 예외가 있습니다.

  1. ksh93에서 함수가 표준 function_name () { … } 구문으로 정의 된 경우 해당 지역 변수는 동적 범위 지정을 따릅니다. 그러나 함수가 ksh 구문 function function_name { … }로 정의 된 경우 해당 지역 변수는 어휘 / 정적 범위 지정을 따르므로 이것에 의해 호출되는 다른 함수에서는 보이지 않습니다.

  2. zshzsh/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] 

출처

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다