グローバル連想配列は、スクリプトを2番目にインポートした場合にのみ表示されます。

グローバル連想配列は、スクリプトを2番目にインポートした場合にのみ表示されます。

私のスクリプト.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最初のソース呼び出しだけでなく、組み込み関数と2番目のソース呼び出しでも私の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とは異なります(タイプ/プロパティと値のみを更新します)Sourcebash vs 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、関数メソッドでwhileother-cmdに拡張されるので、time source ./myfile | other-cmdtimingを渡しますsource ./myfile

使用しても効果はありません(timeキーワードの代わりにスタンドアロンユーティリティがsource=(time source); "${source[@]}" /some/file呼び出されます)。timebash

おすすめ記事