1.ksh93

1.ksh93

~에서https://unix.stackexchange.com/a/381782/674

예를 들어:

integer() { typeset -gi "$1"; }

변수를 정수로 만들려면 // 를 사용할 수 있습니다 mksh. yashzshbash아직 선언되지 않은 변수에 대해서만 작동합니다 .현지의발신자:

$ bash -c 'f() { declare a; integer a; a=1+1; echo "$a"; }; integer() { typeset -gi "$1"; }; f'
1+1
$ bash -c 'f() { integer a; a=1+1; echo "$a"; }; integer() { typeset -gi "$1"; }; f'
2

export var아니고 typeset -x var도 아닙니다 typeset -gx var. export변수가 이미 존재하는 경우 새 변수를 선언하지 않고 속성을 추가합니다. readonlyvs. 와 typeset -r동일

배쉬의 경우,

  • f첫 번째 예 에서 내부 선언과 다른 것을 integer a선언하거나 a내부 선언에 전역 범위를 갖도록 하려면 어떻게 해야 합니까 ? 왜 출력되나요 ?afaf1+1

  • f두 번째 예 에서는 전역 범위가 integer a 선언 되어 있습니까 a? 왜 출력되나요 2?

zsh에 대해서도 동일한 질문입니다. 단, 첫 번째 예제가 bash 2대신 출력되는 이유는 무엇입니까 1+1?

내가 맞나요?

  • 적어도 예제에서는 bash와 zsh 모두 동적 범위 지정을 사용합니까?
  • -gbash 및 zsh의 옵션은 typeset존재하지 않는 변수를 전역 범위로 선언하거나 기존 변수를 전역 범위로 변경하는 것을 의미합니까?

감사해요.

답변1

  • 프로그래밍 언어로정적 범위, 예를 들어 대부분의 다른 프로그래밍 언어(예: C),

    모든 함수에는 전역 범위와 로컬 범위가 있습니다. 함수에 나타나는 변수는 함수 전용이거나 전역 변수입니다.

    함수는 그 중 하나만 액세스할 수 있습니다.그것은지역 또는 전역 변수. 참조로 전달하는 것 외에는 다른 함수(또는 해당 호출자)의 변수에 액세스할 수 없습니다.

  • 프로그래밍 언어로동적 범위 지정,

    함수는 호출자의 변수를 볼 수 있으며 함수 호출 트리의 각 함수에는 범위가 있습니다. 범위 지정은 변수가 서로 쌓여 있는 러시아 마트료시카 인형과 같습니다.

    이 범위 스택에서는글로벌범위의 유일한 특별한 점은 범위가 가장 아래에 있다는 것입니다. 그러나 함수가 호출 트리의 함수에 의해 지역 변수로 마스크된 경우 함수는 해당 범위의 변수를 반드시 볼 수는 없습니다. 따라서 전역 범위와 로컬 범위가 없습니다.


이곳의 역사를 아는 것이 도움이 됩니다.

1.ksh93

  1. 존재하다 ksh93,ksh 구문을 사용하여 선언된 함수( function f {...}),다음과 같이정적 범위.

    typeset함수 내에서 선언된 변수는 해당 함수에 대해 로컬입니다.

    a=global_a
    function f {
      typeset a=f_a
      g
    }
    
    function g {
      echo "$a"
    }
    
    f
    

    출력됩니다 global_a.

    typeset -i var기능에서 유형이 변경되었습니다.현지의 var변수가 함수 범위에서 아직 인스턴스화되지 않은 경우 변수가 인스턴스화됩니다.

  2. 존재하다 ksh93,Bourne 구문을 사용하여 선언된 함수( f() {...})범위 지정이 전혀 없습니다. 이와 관련하여 함수의 코드는 다음과 같습니다.임베디드함수 호출자에서, 그 안에 나타나는 모든 변수는 호출자와 동일한 범위를 가지므로 호출 트리에서 ksh 구문을 사용하여 전역 또는 로컬로 선언된 최상위 함수의 경우. typeset변수는 최상위 함수에서 선언됩니다(또는 호출 트리에 ksh 구문 함수가 없는 경우 전역적으로).

    예를 들어, ksh-syntax 함수에서 모든 변수는 비공개 또는 전역 변수이므로 integeras를 구현하려면 bash다음을 수행해야 합니다.

    integer() { typeset -i "$1"; }
    

    그건Bourne 함수 구문 사용이것은 범위 지정을 전혀 수행하지 않습니다.

    또는ksh 구문 사용:

    function integer { typeset -i "$1"; }
    

    그러나 다음과 같이 호출됩니다.

    . integer var
    

    (즉,사용.., 정수 코드는 스크립트에서 ()를 호출할 때 와 마찬가지로 호출자의 컨텍스트에서 해석됩니다 .source

    또는 사용ksh 구문:

    function integer { typeset -ni "$1"; }
    

    어디변수가 참조로 전달됩니다.-nC나 대부분의 다른 프로그래밍 언어에서 하는 것과 같습니다 .

2. 다른 모든 Bourne 유사 쉘

다른 모든 Bourne 유사 쉘(ksh88을 포함하여 ksh93은 완전히 다시 작성되었으며정적 범위 지정에 대한 변경은 POSIX 표준에 포함되는 기능의 전제 조건입니다(적어도 고려됨).) 구현동적 범위 지정.

  1. 함수 내에서 typeset없이 선언된 변수는 해당 함수의 로컬 범위를 갖습니다.-g

    예를 들어, typeset -i var변수를 로컬(현재 함수 범위 내에서) 선언하고 설정합니다.정수속성.

    예를 들어, 상단의 코드에서는 모두 출력입니다 f_a. 즉, g로컬 변수가 실제로 표시됩니다 f.

    또 다른 예로, 변수가 f선언 되지 않은 경우 g호출됩니다 h.hvar현지의g해당 범위 내에서는 의 변수를 볼 수 있으며 , 로컬 로 선언되지 않은 f경우 의 변수를 볼 수도 있고 , 맨 아래 범위의 변수를 볼 수도 있습니다.gvar

  2. 전체적으로 bash, zsh, yash, mksh,다음 명령을 사용하면 함수에 로컬로 만들지 않고도 함수에서 변수의 유형이나 값을 변경할 수 있습니다.typeset -g. integer인용한 예의 이 기능 과 같습니다 . 하지만 쉘에 따라 다르게 수행됩니다.

    • 존재하다 mksh, yash,zsh, typeset -g 하단 변수에 영향을 미치지 않습니다(글로벌) 범위이지만 현재 정의된 범위 내에서.

      예를 들어 while은 typeset -i var로컬 변수(현재 함수 범위에서)를 선언하고 설정합니다.정수속성, typeset -gi var뒷부분만 실행됩니다(범위에는 영향을 주지 않음 var).

      예를 들어, 함수가 integer위 함수를 호출하여 다음과 같이 정수 속성을 변수에 추가하는 경우:

      f() {
       local myvar
       integer myvar
       ...
      }
      

      integer변경 하려는 속성그것은 myvar인식하지 못하고 액세스할 수 없는 전역 범위의 변수가 아닌 변수입니다.

    • 존재하다bash, typeset -g변수에 영향을 미치는 인스턴스전역(최하위 수준) 범위. 그것이 의미하는 바는 이지만 g, 와 같은 동적 범위에서는 잘 작동하지 않습니다 bash.

      예를 들어, 질문의 첫 번째 예에서 1+1 출력은 정수 속성이 변수에 추가되지 않았음을 나타냅니다. 에 추가되었습니다전역 범위의 변수이지만 a함수가 액세스할 수 있는 변수는 아닙니다.f

관련 정보