Global associative array only visible when the script is sourced a second timebash vs zsh: scoping and...

Gofer work in exchange for LoR

Good way to stop electrolyte tabs from turning into powder?

How can I enter recovery mode (for Mac OS, on an iMac) remotely?

Unsolved Problems due to Lack of Computational Power

Units of measurement, especially length, when body parts vary in size among races

What is the purpose/function of this power inductor in parallel?

Why do we use low resistance cables to minimize power losses?

What allows us to use imaginary numbers?

Animate flow lines of time-dependent 3D dynamical system

Is a USB 3.0 device possible with a four contact USB 2.0 connector?

A Magic Diamond

How to render "have ideas above his station" into German

What should I do if actually I found a serious flaw in someone's PhD thesis and an article derived from that PhD thesis?

Attacking the Hydra

What exactly happened to the 18 crew members who were reported as "missing" in "Q Who"?

What was the intention with the Commodore 128?

How would armour (and combat) change if the fighter didn't need to actually wear it?

Is there a fallacy about "appeal to 'big words'"?

Setting up a Mathematical Institute of Refereeing?

How do I pass a "list of lists" as the argument to a function of the form F[x,y]?

Build a mob of suspiciously happy lenny faces ( ͡° ͜ʖ ͡°)

String routines

How do I answer an interview question about how to handle a hard deadline I won't be able to meet?

Why should I pay for an SSL certificate?



Global associative array only visible when the script is sourced a second time


bash vs zsh: scoping and `typeset -g`How to initialize a read-only, global, associative array in Bash?Error when constructing an associative arraybash silently does function return on (re-)declare of global associative read-only arraydisplay array in a function - not working“bad array subscript” error when adding entry to an associative arrayCreate an associative array from the output of two commandsReturn the output of a command into an associative arrayPass associative array as parameter list to script






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







2















I have the following script called .bash_functions.test which is already sourced by my .bash_functions script:



# 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[*]}"
}


And when I run the test1 function I see this:



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


Finally, when I source the script once more and re-run the test1 function I see this:



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


In fact, I use my Source function in the first source call and the source builtin and the second source call:



$ 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 "$@"
}


And here is what happens:



$ 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


Why is it working like this?










share|improve this question






















  • 1





    Does your .bash_functions source .bash_functions.test from within a function by any chance? If that was the case, the declare would cause that associative array to be declared local to that function and you'd need declare -gA to make sure the variable is declared in the global scope.

    – Stéphane Chazelas
    yesterday













  • @StéphaneChazelas You're right. Can you convert your comment to an answer?

    – SebMa
    yesterday


















2















I have the following script called .bash_functions.test which is already sourced by my .bash_functions script:



# 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[*]}"
}


And when I run the test1 function I see this:



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


Finally, when I source the script once more and re-run the test1 function I see this:



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


In fact, I use my Source function in the first source call and the source builtin and the second source call:



$ 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 "$@"
}


And here is what happens:



$ 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


Why is it working like this?










share|improve this question






















  • 1





    Does your .bash_functions source .bash_functions.test from within a function by any chance? If that was the case, the declare would cause that associative array to be declared local to that function and you'd need declare -gA to make sure the variable is declared in the global scope.

    – Stéphane Chazelas
    yesterday













  • @StéphaneChazelas You're right. Can you convert your comment to an answer?

    – SebMa
    yesterday














2












2








2


1






I have the following script called .bash_functions.test which is already sourced by my .bash_functions script:



# 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[*]}"
}


And when I run the test1 function I see this:



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


Finally, when I source the script once more and re-run the test1 function I see this:



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


In fact, I use my Source function in the first source call and the source builtin and the second source call:



$ 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 "$@"
}


And here is what happens:



$ 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


Why is it working like this?










share|improve this question
















I have the following script called .bash_functions.test which is already sourced by my .bash_functions script:



# 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[*]}"
}


And when I run the test1 function I see this:



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


Finally, when I source the script once more and re-run the test1 function I see this:



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


In fact, I use my Source function in the first source call and the source builtin and the second source call:



$ 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 "$@"
}


And here is what happens:



$ 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


Why is it working like this?







bash associative-array






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday









Jeff Schaller

49k11 gold badges72 silver badges162 bronze badges




49k11 gold badges72 silver badges162 bronze badges










asked yesterday









SebMaSebMa

3891 gold badge4 silver badges14 bronze badges




3891 gold badge4 silver badges14 bronze badges











  • 1





    Does your .bash_functions source .bash_functions.test from within a function by any chance? If that was the case, the declare would cause that associative array to be declared local to that function and you'd need declare -gA to make sure the variable is declared in the global scope.

    – Stéphane Chazelas
    yesterday













  • @StéphaneChazelas You're right. Can you convert your comment to an answer?

    – SebMa
    yesterday














  • 1





    Does your .bash_functions source .bash_functions.test from within a function by any chance? If that was the case, the declare would cause that associative array to be declared local to that function and you'd need declare -gA to make sure the variable is declared in the global scope.

    – Stéphane Chazelas
    yesterday













  • @StéphaneChazelas You're right. Can you convert your comment to an answer?

    – SebMa
    yesterday








1




1





Does your .bash_functions source .bash_functions.test from within a function by any chance? If that was the case, the declare would cause that associative array to be declared local to that function and you'd need declare -gA to make sure the variable is declared in the global scope.

– Stéphane Chazelas
yesterday







Does your .bash_functions source .bash_functions.test from within a function by any chance? If that was the case, the declare would cause that associative array to be declared local to that function and you'd need declare -gA to make sure the variable is declared in the global scope.

– Stéphane Chazelas
yesterday















@StéphaneChazelas You're right. Can you convert your comment to an answer?

– SebMa
yesterday





@StéphaneChazelas You're right. Can you convert your comment to an answer?

– SebMa
yesterday










1 Answer
1






active

oldest

votes


















2














declare/typeset without -g declares variables in the current scope in addition to setting the type.



Here, because declare -A audioExtension=(...) ends up being run within the Source function, that causes the audioExtension variable to be declared local to that function, and as a consequence its definition to be lost once Source returns.



You could change it to typeset -Ag audioExtension=(...) which always declares the variable in the global scope (it's different from zsh/mksh/yash where typeset -g only prevents the variable from being made local (only updates the type/attributes and value); it makes a difference when your Source function is called from another function itself; see bash vs zsh: scoping and `typeset -g` for details).



If you used ksh93 instead of bash (that's the shell bash borrowed that associative array syntax from), you could define your Source function as:



Source() {
...
}


as opposed to:



function Source {
...
}


In ksh93, functions defined with the Bourne-style func() cmd syntax don't have a local scope while function func { ones have static local scope (there, there's only one global scope and one local per-function scope, not a stack of local scopes).



In bash (and other shells with local scoping), there's no similar way to have a function that doesn't introduce a new scope. You could use an alias instead like:



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


(note that the aliases are expanded at the time code is read, not at the time it's executed).



It would make a functional difference compared to your function approach in that in:



Source ./myfile | other-cmd


We would be timing both source myfile and other-cmd as it's expanded to time source ./myfile | other-cmd while in the function approach we would only by timing source ./myfile.



Using source=(time source); "${source[@]}" /some/file wouldn't work (it would invoke the time standalone utility instead of the bash time keyword).






share|improve this answer






























    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "106"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f535698%2fglobal-associative-array-only-visible-when-the-script-is-sourced-a-second-time%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    declare/typeset without -g declares variables in the current scope in addition to setting the type.



    Here, because declare -A audioExtension=(...) ends up being run within the Source function, that causes the audioExtension variable to be declared local to that function, and as a consequence its definition to be lost once Source returns.



    You could change it to typeset -Ag audioExtension=(...) which always declares the variable in the global scope (it's different from zsh/mksh/yash where typeset -g only prevents the variable from being made local (only updates the type/attributes and value); it makes a difference when your Source function is called from another function itself; see bash vs zsh: scoping and `typeset -g` for details).



    If you used ksh93 instead of bash (that's the shell bash borrowed that associative array syntax from), you could define your Source function as:



    Source() {
    ...
    }


    as opposed to:



    function Source {
    ...
    }


    In ksh93, functions defined with the Bourne-style func() cmd syntax don't have a local scope while function func { ones have static local scope (there, there's only one global scope and one local per-function scope, not a stack of local scopes).



    In bash (and other shells with local scoping), there's no similar way to have a function that doesn't introduce a new scope. You could use an alias instead like:



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


    (note that the aliases are expanded at the time code is read, not at the time it's executed).



    It would make a functional difference compared to your function approach in that in:



    Source ./myfile | other-cmd


    We would be timing both source myfile and other-cmd as it's expanded to time source ./myfile | other-cmd while in the function approach we would only by timing source ./myfile.



    Using source=(time source); "${source[@]}" /some/file wouldn't work (it would invoke the time standalone utility instead of the bash time keyword).






    share|improve this answer
































      2














      declare/typeset without -g declares variables in the current scope in addition to setting the type.



      Here, because declare -A audioExtension=(...) ends up being run within the Source function, that causes the audioExtension variable to be declared local to that function, and as a consequence its definition to be lost once Source returns.



      You could change it to typeset -Ag audioExtension=(...) which always declares the variable in the global scope (it's different from zsh/mksh/yash where typeset -g only prevents the variable from being made local (only updates the type/attributes and value); it makes a difference when your Source function is called from another function itself; see bash vs zsh: scoping and `typeset -g` for details).



      If you used ksh93 instead of bash (that's the shell bash borrowed that associative array syntax from), you could define your Source function as:



      Source() {
      ...
      }


      as opposed to:



      function Source {
      ...
      }


      In ksh93, functions defined with the Bourne-style func() cmd syntax don't have a local scope while function func { ones have static local scope (there, there's only one global scope and one local per-function scope, not a stack of local scopes).



      In bash (and other shells with local scoping), there's no similar way to have a function that doesn't introduce a new scope. You could use an alias instead like:



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


      (note that the aliases are expanded at the time code is read, not at the time it's executed).



      It would make a functional difference compared to your function approach in that in:



      Source ./myfile | other-cmd


      We would be timing both source myfile and other-cmd as it's expanded to time source ./myfile | other-cmd while in the function approach we would only by timing source ./myfile.



      Using source=(time source); "${source[@]}" /some/file wouldn't work (it would invoke the time standalone utility instead of the bash time keyword).






      share|improve this answer






























        2












        2








        2







        declare/typeset without -g declares variables in the current scope in addition to setting the type.



        Here, because declare -A audioExtension=(...) ends up being run within the Source function, that causes the audioExtension variable to be declared local to that function, and as a consequence its definition to be lost once Source returns.



        You could change it to typeset -Ag audioExtension=(...) which always declares the variable in the global scope (it's different from zsh/mksh/yash where typeset -g only prevents the variable from being made local (only updates the type/attributes and value); it makes a difference when your Source function is called from another function itself; see bash vs zsh: scoping and `typeset -g` for details).



        If you used ksh93 instead of bash (that's the shell bash borrowed that associative array syntax from), you could define your Source function as:



        Source() {
        ...
        }


        as opposed to:



        function Source {
        ...
        }


        In ksh93, functions defined with the Bourne-style func() cmd syntax don't have a local scope while function func { ones have static local scope (there, there's only one global scope and one local per-function scope, not a stack of local scopes).



        In bash (and other shells with local scoping), there's no similar way to have a function that doesn't introduce a new scope. You could use an alias instead like:



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


        (note that the aliases are expanded at the time code is read, not at the time it's executed).



        It would make a functional difference compared to your function approach in that in:



        Source ./myfile | other-cmd


        We would be timing both source myfile and other-cmd as it's expanded to time source ./myfile | other-cmd while in the function approach we would only by timing source ./myfile.



        Using source=(time source); "${source[@]}" /some/file wouldn't work (it would invoke the time standalone utility instead of the bash time keyword).






        share|improve this answer















        declare/typeset without -g declares variables in the current scope in addition to setting the type.



        Here, because declare -A audioExtension=(...) ends up being run within the Source function, that causes the audioExtension variable to be declared local to that function, and as a consequence its definition to be lost once Source returns.



        You could change it to typeset -Ag audioExtension=(...) which always declares the variable in the global scope (it's different from zsh/mksh/yash where typeset -g only prevents the variable from being made local (only updates the type/attributes and value); it makes a difference when your Source function is called from another function itself; see bash vs zsh: scoping and `typeset -g` for details).



        If you used ksh93 instead of bash (that's the shell bash borrowed that associative array syntax from), you could define your Source function as:



        Source() {
        ...
        }


        as opposed to:



        function Source {
        ...
        }


        In ksh93, functions defined with the Bourne-style func() cmd syntax don't have a local scope while function func { ones have static local scope (there, there's only one global scope and one local per-function scope, not a stack of local scopes).



        In bash (and other shells with local scoping), there's no similar way to have a function that doesn't introduce a new scope. You could use an alias instead like:



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


        (note that the aliases are expanded at the time code is read, not at the time it's executed).



        It would make a functional difference compared to your function approach in that in:



        Source ./myfile | other-cmd


        We would be timing both source myfile and other-cmd as it's expanded to time source ./myfile | other-cmd while in the function approach we would only by timing source ./myfile.



        Using source=(time source); "${source[@]}" /some/file wouldn't work (it would invoke the time standalone utility instead of the bash time keyword).







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited yesterday

























        answered yesterday









        Stéphane ChazelasStéphane Chazelas

        330k58 gold badges641 silver badges1008 bronze badges




        330k58 gold badges641 silver badges1008 bronze badges

































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f535698%2fglobal-associative-array-only-visible-when-the-script-is-sourced-a-second-time%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Taj Mahal Inhaltsverzeichnis Aufbau | Geschichte | 350-Jahr-Feier | Heutige Bedeutung | Siehe auch |...

            Baia Sprie Cuprins Etimologie | Istorie | Demografie | Politică și administrație | Arii naturale...

            Nicolae Petrescu-Găină Cuprins Biografie | Opera | In memoriam | Varia | Controverse, incertitudini...