`declare name`과 `declare -g`는 무엇을 합니까?

`declare name`과 `declare -g`는 무엇을 합니까?
  1. 무엇인가요

    declare name
    

    옵션이 제공되지 않으면 어떻게 되나요? 문자열 변수의 이름을 선언합니까?

  2. 무엇인가요

    declare -g
    

    변수 이름을 제공하지 않으면 어떻게 해야 합니까? 전역 속성을 가진 모든 변수의 값을 표시합니까?

declareBash 매뉴얼 설명에서 답을 찾지 못했습니다.

감사해요.

답변1

특히 셸에서의 변수 처리 및 범위 지정은 bash매우 모호하고 직관적이지 않을 수 있습니다(때로는 버그가 있을 수도 있음).

ksh비슷한 기능을 가지고 있습니다 typeset. ksh, zsh, yash가지다 typeset. bashHas 는 typeset별칭으로 사용되며 has 와 declare호환 됩니다 ksh. 대부분의 쉘에는 이 기능이 있으며 일부 기능을 구현합니다 .zshdeclaretypesetbashexportreadonlylocaltypeset

bash작가가 선택한 declare이유 중 하나 typesettypeset장르를 설정하는 것뿐만 아니라;주장하다변수: 유형, 속성 및/또는 값과 함께 주어진 범위에 도입됩니다.

에서 bash변수는 다음과 같습니다.

  • 알 수 없음(예: 설정되거나 선언되지 않은 경우)
  • 명령문( 이후 declare)
  • 설정합니다(값이 주어지면 비어 있을 수 있음).

유형은 다양할 수 있습니다.

  • 스칼라
  • 대량으로
  • 연관 배열

그리고 다음과 같은 몇 가지 속성이 있습니다.

  • 정수
  • 출구
  • 읽기 전용
  • 모두 소문자/모두 대문자
  • 명명 참조

(유형과 속성 간의 구분이 상당히 모호할 수 있지만)

유형과 속성의 모든 조합이 지원되거나 유효한 것은 아닙니다.

이제 declare현재 범위에서 변수를 선언합니다. bash, 동적 범위를 구현하더라도 가장 바깥쪽 범위를 특별하게 처리합니다. ~라고 불린다글로벌범위.

declare호출될 때의 동작은 매우 다릅니다.글로벌범위 및 함수에 있는 경우(서브쉘에 의해 도입되거나 환경과 관련된 별도의 범위에 대해 말하는 것이 아닙니다).

declare var함수 내에서 작업을 수행하고 동일한 변수가 동일한 범위에서 선언되지 않았다고 가정 하면주장하다새로운초기에 설정되지 않은 변수로, var상위 범위(함수 호출자)에 존재할 수 있는 잠재적인 변수를 숨깁니다.

이는 일종의 스택을 통해 구현된 동적 범위 지정입니다. 함수가 종료되면 변수의 상태, 유형, 속성 및 값은 함수가 호출되었을 때의 상태(스택에서 팝됨)로 복원됩니다.

그러나 함수 외부(전역 범위 내)에서는 declare변수가 실제로 선언되지만 이전에 설정되어 있으면 설정 해제되도록 초기화되지 않습니다( declare동일 함수 범위 내에서 두 번째로 사용할 때와 동일). 유형이 지정되면 변수의 값이 변환될 수 있지만 모든 변환 경로가 허용되는 것은 아니며(스칼라에서 배열/해시로만) 속성을 추가하거나 제거할 수 있습니다.

에서 bash함수는 declare -g가장 바깥쪽("전역") 범위의 스택 맨 아래에 있는 변수에 대해 작동합니다.

declare -gksh93에서 영감을 받다 typeset -g. 그러나 ksh93전역 범위가 다르고 각 함수 범위와 별개인 정적 범위 지정을 구현합니다. 동적 범위로 동일한 작업을 수행하는 것은 거의 의미가 없습니다. typeset -g( mksh, zsh, )가 있는 다른 모든 yash셸 에서는 typeset -g새 지역 변수를 인스턴스화하지 않고 변수의 일부 속성을 변경하는 데 사용됩니다.

에서는 bash사람들이 보통 같은 목적으로 사용하지만 현재 변수가 아닌 가장 바깥쪽 범위 변수에 영향을 주기 때문에 항상 작동하지는 않습니다.

예를 들어:

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마찬가지다 .

또한 변수 가 현재 범위에서 선언된 unset경우 에만 설정을 해제합니다(전역 범위는 제외하지만 선언은 유지합니다. 속성과 값을 제거하고 변수는 더 이상 배열이나 해시가 아닙니다.) bashnamerefs에서는 참조된 변수를 설정 해제합니다). 그렇지 않으면 위에서 언급한 스택에서 변수 레이어를 팝합니다. bash버전 5.0 이상에서는 옵션 localvar_unset을 설정하여 해결할 수 있습니다.

결론적으로:

 declare var

함수 내에서 호출될 때 var이전에 동일한 함수에서 선언되지 않은 경우 유형의 변수를 선언합니다.스칼라속성이 없으며 초기에 설정되지 않습니다.

함수 외부에서 호출되거나 var동일한 함수에서 이미 선언된 경우 새로운 유형이나 속성을 지정하지 않으므로 아무런 효과가 없습니다.

declare -g var

호출되는 곳마다 var가장 바깥쪽("전역") 범위를 선언합니다.발표하다,유형스칼라, 속성이 없고 이전에 범위에서 알려지지 않은 경우 값이 없으며(모든 의도와 목적에 대해 출력에 표시된다는 점을 제외하면 알 수 없는 변수와 동일합니다 typeset -p) 그 외에는 아무 작업도 수행하지 않습니다.

어떤 경우든 명령이 실행되는 컨텍스트에서 변수에 액세스하지 못할 수도 있습니다.

f() { local a; g; }; g() { typeset -g a=123; echo "$a"; }; f

아무것도 출력되지 않습니다.

답변2

  1. declare namename속성 없이 이름이 지정된 변수를 선언합니다 . ${name:not set}예를 들어 다음을 사용하여 그 효과를 확인할 수 있습니다. 선언된 변수는 배열이 아니고 정수 속성이 설정되어 있지 않으므로 문자열 변수로 처리할 수 있지만 산술 표현식에서는 0으로 평가됩니다.

  2. ~에서맨페이지:

    이 옵션은 쉘 함수 내에서 실행되는 -g경우에도 전역적으로 변수를 생성하거나 수정하도록 합니다 . declare다른 모든 경우에는 무시됩니다.

    따라서 declare -g매개변수가 없으면 와 동일합니다 declare.

답변3

declare name

에서https://www.gnu.org/software/bash/manual/bashref.html#Bash-Builtins

변수를 선언하고 속성을 할당합니다.

옵션을 제공하지 않았으므로 속성이 할당되지 않았고 name변수가 생성되었습니다. 값이 제공되지 않았으므로 값이 할당되지 않았습니다.

declare -g

-g 옵션은 명령문이 쉘 함수 내에서 실행되는 경우에도 전역 범위에서 변수를 강제로 생성하거나 수정합니다. 다른 모든 경우에는 무시됩니다.

를 제공하지 않으므로 name변수가 생성되지 않으므로 무시됩니다. 스스로 봐:

declare -g > foo
declare > bar
diff foo bar

유일한 차이점은 Bash 변수의 값일 수 $_있으며 이전 명령을 기반으로 할 수 있으며 PIPESTATUS반환된 변수 목록에는 다른 차이점이 없습니다.

관련 정보