linux - Odd results from Bash-4 recursion -


i devised simple test see how bash behaves recursion, , not understand results.

test:

  1. assign global variable x in shell
  2. create function f() assigns variable local x of same name
  3. assign local x value of global x i.e. local x=$x
  4. recurse function few times , check whether, on each recursion, uses global x or local x previous turn of function

i expected 1 of 2 outcomes:

  • on each recursion, local x previous f() new "global" x, i.e. x in next-up scope, indicate each recursion creates new scope beneath previous scope
  • on each recursion, previous local x value forgotten, , each new local x=$x reassign value of global x assigned. indicate bash creates adjacent scopes.

i didn't of these. got weird. below copy-paste terminal.

i assign global variable in shell:

user@ubuntu-zesty:~$ x=1 

i create function f() in shell creates local x, assigns value of global x it, enters while loop, adds 1 local x (i assume local one), prints new local x value, , calls itself. repeat 5 or 6 times.

user@ubuntu-zesty:~$ f() { local x=$x; while [ $x -lt 6 ]; x=$(( $x + 1 )); echo $x; sleep 1; f; done; } 

then call f(), , output baffling.

user@ubuntu-zesty:~$ f 2 3 4 5 6 6 5 6 6 4 5 6 6 5 6 6 3 4 5 6 6 5 6 6 4 5 6 6 5 6 6 

at point exited on own. , expected global x unaffected.

user@ubuntu-zesty:~$ echo $x 1 

so what's going on here? using global x, local x? please if know what's going on here don't spare me gory details.

lastly, fun, graph of output:

 1 ==  2 ===  3 ====  4 =====  5 ======  6 ======  7 =====  8 ======  9 ====== 10 ==== 11 ===== 12 ====== 13 ====== 14 ===== 15 ====== 16 ====== 17 === 18 ==== 19 ===== 20 ====== 21 ====== 22 ===== 23 ====== 24 ====== 25 ==== 26 ===== 27 ====== 28 ====== 29 ===== 30 ====== 31 ====== 

specs:

  • bash-4.4.5(1)-release
  • x86_64 ubuntu zesty
  • linux kernel 4.10.0-17-generic
  • vmware workstation 12 virtual machine

i think best way visualize dynamic scoping explained @chepner in answer modify function slightly:

function f() {    local x="$x"   while [ "$x" -lt 6 ];      x=$((x + 1))     echo "${funcname[*]}" "$x" # print call stack     sleep 1     f   done } 

and see how values increase: if follow output columns, can debug happens @ each level.

$ f f f f f f 2 f f f f f f 3 f f f f f f f 4 f f f f f f f f 5 f f f f f f f f f 6 f f f f f f f f 6 f f f f f f f 5 f f f f f f f f 6 f f f f f f f 6 f f f f f f 4 f f f f f f f 5 f f f f f f f f 6 ... 

Comments