~에서https://unix.stackexchange.com/a/381782/674
예를 들어:
integer() { typeset -gi "$1"; }
변수를 정수로 만들려면 // 를 사용할 수 있습니다
mksh
.yash
zsh
bash
아직 선언되지 않은 변수에 대해서만 작동합니다 .현지의발신자:$ 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
변수가 이미 존재하는 경우 새 변수를 선언하지 않고 속성을 추가합니다.readonly
vs. 와typeset -r
동일
배쉬의 경우,
f
첫 번째 예 에서 내부 선언과 다른 것을integer a
선언하거나a
내부 선언에 전역 범위를 갖도록 하려면 어떻게 해야 합니까 ? 왜 출력되나요 ?a
f
a
f
1+1
f
두 번째 예 에서는 전역 범위가integer a
선언 되어 있습니까a
? 왜 출력되나요2
?
zsh에 대해서도 동일한 질문입니다. 단, 첫 번째 예제가 bash 2
대신 출력되는 이유는 무엇입니까 1+1
?
내가 맞나요?
- 적어도 예제에서는 bash와 zsh 모두 동적 범위 지정을 사용합니까?
-g
bash 및 zsh의 옵션은typeset
존재하지 않는 변수를 전역 범위로 선언하거나 기존 변수를 전역 범위로 변경하는 것을 의미합니까?
감사해요.
답변1
프로그래밍 언어로정적 범위, 예를 들어 대부분의 다른 프로그래밍 언어(예: C),
모든 함수에는 전역 범위와 로컬 범위가 있습니다. 함수에 나타나는 변수는 함수 전용이거나 전역 변수입니다.
함수는 그 중 하나만 액세스할 수 있습니다.그것은지역 또는 전역 변수. 참조로 전달하는 것 외에는 다른 함수(또는 해당 호출자)의 변수에 액세스할 수 없습니다.
프로그래밍 언어로동적 범위 지정,
함수는 호출자의 변수를 볼 수 있으며 함수 호출 트리의 각 함수에는 범위가 있습니다. 범위 지정은 변수가 서로 쌓여 있는 러시아 마트료시카 인형과 같습니다.
이 범위 스택에서는글로벌범위의 유일한 특별한 점은 범위가 가장 아래에 있다는 것입니다. 그러나 함수가 호출 트리의 함수에 의해 지역 변수로 마스크된 경우 함수는 해당 범위의 변수를 반드시 볼 수는 없습니다. 따라서 전역 범위와 로컬 범위가 없습니다.
이곳의 역사를 아는 것이 도움이 됩니다.
1.ksh93
존재하다
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
변수가 함수 범위에서 아직 인스턴스화되지 않은 경우 변수가 인스턴스화됩니다.존재하다
ksh93
,Bourne 구문을 사용하여 선언된 함수(f() {...}
)범위 지정이 전혀 없습니다. 이와 관련하여 함수의 코드는 다음과 같습니다.임베디드함수 호출자에서, 그 안에 나타나는 모든 변수는 호출자와 동일한 범위를 가지므로 호출 트리에서 ksh 구문을 사용하여 전역 또는 로컬로 선언된 최상위 함수의 경우.typeset
변수는 최상위 함수에서 선언됩니다(또는 호출 트리에 ksh 구문 함수가 없는 경우 전역적으로).예를 들어, ksh-syntax 함수에서 모든 변수는 비공개 또는 전역 변수이므로
integer
as를 구현하려면bash
다음을 수행해야 합니다.integer() { typeset -i "$1"; }
그건Bourne 함수 구문 사용이것은 범위 지정을 전혀 수행하지 않습니다.
또는ksh 구문 사용:
function integer { typeset -i "$1"; }
그러나 다음과 같이 호출됩니다.
. integer var
(즉,사용
.
.
, 정수 코드는 스크립트에서 ()를 호출할 때 와 마찬가지로 호출자의 컨텍스트에서 해석됩니다 .source
또는 사용ksh 구문:
function integer { typeset -ni "$1"; }
어디변수가 참조로 전달됩니다.
-n
C나 대부분의 다른 프로그래밍 언어에서 하는 것과 같습니다 .
2. 다른 모든 Bourne 유사 쉘
다른 모든 Bourne 유사 쉘(ksh88을 포함하여 ksh93은 완전히 다시 작성되었으며정적 범위 지정에 대한 변경은 POSIX 표준에 포함되는 기능의 전제 조건입니다(적어도 고려됨).) 구현동적 범위 지정.
함수 내에서
typeset
없이 선언된 변수는 해당 함수의 로컬 범위를 갖습니다.-g
예를 들어,
typeset -i var
변수를 로컬(현재 함수 범위 내에서) 선언하고 설정합니다.정수속성.예를 들어, 상단의 코드에서는 모두 출력입니다
f_a
. 즉,g
로컬 변수가 실제로 표시됩니다f
.또 다른 예로, 변수가
f
선언 되지 않은 경우g
호출됩니다h
.h
var
현지의g
해당 범위 내에서는 의 변수를 볼 수 있으며 , 로컬 로 선언되지 않은f
경우 의 변수를 볼 수도 있고 , 맨 아래 범위의 변수를 볼 수도 있습니다.g
var
전체적으로
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