전역 연관 배열은 스크립트를 두 번째로 가져올 때만 표시됩니다.

전역 연관 배열은 스크립트를 두 번째로 가져올 때만 표시됩니다.

내 스크립트 .bash_functions.test에서 선택한 다음 스크립트를 호출했습니다 ..bash_functions

# vim: set syn=sh noet:

mp4Options_BIS="-movflags +frag_keyframe"
declare -A audioExtension=( [libspeex]=spx [speex]=spx [opus]=opus [vorbis]=ogg [aac]=m4a [mp3]=mp3 [mp2]=mp2 [ac3]=ac3 [wmav2]=wma [pcm_dvd]=wav [pcm_s16le]=wav )

function test1 {
    echo "=> mp4Options_BIS = $mp4Options_BIS"
    echo "=> audioExtension = ${audioExtension[*]}"
}

함수 를 실행하면 test1다음이 표시됩니다.

=> mp4Options_BIS = -movflags +frag_keyframe
=> audioExtension = 

마지막으로 스크립트를 다시 가져와서 test1함수를 다시 실행하면 다음이 표시됩니다.

=> mp4Options_BIS = -movflags +frag_keyframe
=> audioExtension = ac3 wma opus mp3 wav mp2 wav spx m4a spx ogg

실제로 저는 Source첫 번째 소스 호출뿐만 아니라 내장 함수와 두 번째 소스 호출에서도 source내 함수를 사용하고 있습니다 .

$ grep -r .bash_functions.test 
.bash_functions:source $initDir/.bash_functions.test
$ type Source 
Source is a function
Source () 
{ 
    test "$debug" -gt 0 && time source "$@" && echo || source "$@"
}

무슨 일이 일어나는가?

$ Source .initBash/.bash_functions.test
$ test1
=> mp4Options_BIS = -movflags +frag_keyframe
=> audioExtension = 
$ source .initBash/.bash_functions.test
$ test1
=> mp4Options_BIS = -movflags +frag_keyframe
=> audioExtension = ac3 wma opus mp3 wav mp2 wav spx m4a spx ogg

왜 이런 식으로 작동합니까?

답변1

declare/ typeset없이 -g유형을 설정하는 것 외에도 현재 범위의 변수를 선언합니다.

여기서는 함수 내에서 실행 declare -A audioExtension=(...)되기 때문에 변수가 해당 함수에 대해 로컬로 선언되므로 일단 반환되면 해당 정의가 손실됩니다.SourceaudioExtensionSource

typeset -Ag audioExtension=(...)항상 전역 범위에서 변수를 선언 하도록 변경할 수 있습니다 ( typeset -g변수가 로컬이 되는 것을 방지하는 zsh/mksh/yash와 다릅니다(유형/속성 및 값만 업데이트). 함수가 Source다른 함수 자체 호출에서 시작될 때; 보다bash 대 zsh: 범위 지정 및 `typeset -g`더 알아보기).

ksh93대신 사용하는 경우 ( 연관 배열 구문을 빌린 bash쉘 ) 함수를 다음과 같이 정의할 수 있습니다.bashSource

Source() {
  ...
}

반대:

function Source {
  ...
}

ksh93에서 func() cmdBourne 스타일 구문을 사용하여 정의된 함수에는 로컬 범위가 없습니다 function func {.변화 없는로컬 범위(여기서만하나글로벌 범위 및하나로컬 범위의 스택이 아닌 로컬 함수별 범위).

(및 로컬 범위가 있는 다른 셸) 에는 bash새 범위를 도입하지 않고 기능을 갖는 유사한 방법이 없습니다. alias비슷한 대안을 사용할 수 있습니다 .

shopt -s expand_aliases
if [ "$debug" -gt 0 ]; then
  alias Source='time source'
else
  alias Source=source
fi

(코드가 확장되면 별칭도 확장됩니다.읽다, 아직 아님처형된).

기능적 접근 방식과 비교하면 기능적 차이가 있습니다.

Source ./myfile | other-cmd

우리는 둘 다 시간을 측정할 것이며 source myfile, 함수 메서드에서 while other-cmd으로 확장되므로 time source ./myfile | other-cmdtiming 을 전달할 것입니다 source ./myfile.

사용해도 아무런 효과가 없습니다( time 키워드 대신 독립 실행형 유틸리티가 source=(time source); "${source[@]}" /some/file호출됩니다 ).timebash

관련 정보