On Sun, 10 Mar 2024 23:09:37 +0800 Adrian Ho <lexfi...@gmail.com> wrote:
> [Apologies, an earlier edition of this bug report was sent from the address > a...@lex.03s.net, which can only be replied to from my internal network. > Please ignore that report. Thanks much!] > > Configuration Information [Automatically generated, do not change]: > Machine: x86_64 > OS: linux-gnu > Compiler: gcc-11 > Compilation CFLAGS: -DSSH_SOURCE_BASHRC > uname output: Linux lex 6.5.0-25-generic #25-Ubuntu SMP PREEMPT_DYNAMIC Wed > Feb 7 14:58:39 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux > Machine Type: x86_64-pc-linux-gnu > > Bash Version: 5.2 > Patch Level: 26 > Release Status: release > > Description: > "local -g var" incorrectly references a local variable in an > enclosing scope, while "local -g var=val" correctly references and modifies > the global variable. > > Repeat-By: > Test script: > > #!/usr/bin/env bash > echo "Bash version: $BASH_VERSION" > > b() { > local -g a=2 > c > } > c() { > local -g a > a=3 > } > > y() { > local z=1 > x > } > x() { > local -g z=2 > w > } > w() { > local -g z > echo "w: z=$z" > z=3 > } > > b; y > echo "a=$a z=$z" > > Expected output: > > Bash version: 5.2.26(1)-release > w: z=2 > a=3 z=3 > > Actual output: > > Bash version: 5.2.26(1)-release > w: z=1 > a=3 z=2 Dynamic scoping can be tremendously confusing. The following examples should help to clarify the present state of affairs. $ x() { local a; y; echo "outer: $a"; } $ y() { local a; a=123; echo "inner: $a"; } $ x; echo "outermost: $a" inner: 123 outer: outermost: This is likely as you would expect. $ y() { local -g a; a=123; echo "inner: $a"; } $ x; echo "outermost: $a" inner: 123 outer: 123 outermost: This may not be. There, the effect of the -g option effectively ends at the outermost scope in which the variable, a, was declared. Namely, that of the x function. $ y() { local -g a=123; echo "inner: $a"; } $ x; echo "outermost: $a" inner: outer: outermost: 123 There, by combining the -g option with assignment syntax, the outermost scope - that which most would consider as being implied by the term, global - is duly reached. The manual states that the "-g option forces variables to be created or modified at the global scope, even when declare is executed in a shell function" and that "it is ignored in all other cases". I would consider this wording insufficient for a user to be able to effectively reason with the difference between the second case and the other two cases presented. -- Kerin Millar