Home > Mobile >  Bash Script Variable Scope inside Function
Bash Script Variable Scope inside Function

Time:06-09

THIS CODE ...

#!/usr/local/bin/bash

getDeclared() {
    
    local v

    v=$( set -o posix ; set )
    IFS=$'\n' read -d '\034' -r -a v <<<"${v}\034"  
    
    echo "${v[*]}"
}

declare -a _hints=()
declare _hint="start.hint"
declare _paths
declare _basepath="root/devops/cloud"
declare _base="/"
declare _hintmaxdepth=0

    echo "${BASH_VERSION}"

    x=$(getDeclared)
    x=($x)
    
    for ((y=0;y<${#x[@]};y  )); do
        [ "${x[y]::1}" == "_" ] && echo "$y: ${x[y]}"$'\n'
    done

    

HAS THIS OUTPUT:

➜  sometest bash working.sh                                                                                                  
5.1.16(1)-release
66: _=posix

67: __CFBundleIdentifier=com.sublimetext.4

68: __CF_USER_TEXT_ENCODING=0x1F6:0x0:0x0

69: _base=/

70: _basepath=root/devops/cloud

71: _hint=start.hint

72: _hintmaxdepth=0

73: _hints=()

SO FAR SO GOOD

However, if I change the function to include the display logic, as seen in ...

THIS CODE ...

#!/usr/local/bin/bash

getDeclared() {
    
    local v
    local x

    v=$( set -o posix ; set )
    IFS=$'\n' read -d '\034' -r -a v <<<"${v}\034"  
    
    x=($v)
    
    for ((y=0;y<${#x[@]};y  )); do
       [ "${x[y]::1}" == "_" ] && echo "$y: ${x[y]}"$'\n'
    done
}

declare -a _hints=()
declare _hint="start.hint"
declare _paths
declare _basepath="root/devops/cloud"
declare _base="/"
declare _hintmaxdepth=0

    echo "${BASH_VERSION}"

    getDeclared

THIS OUTPUT

➜  sometest bash working1.sh                                                                                                 
5.1.16(1)-release
0: BASH=/usr/local/bin/bash

Not what I expected. If I change it to just echo everything (not filtering on the "_"), same result...

THIS CODE ...

#!/usr/local/bin/bash

getDeclared() {
    
    local v
    local x

    v=$( set -o posix ; set )
    IFS=$'\n' read -d '\034' -r -a v <<<"${v}\034"  
    
    x=($v)
    
    for ((y=0;y<${#x[@]};y  )); do
       echo "$y: ${x[y]}"$'\n'
    done
}

declare -a _hints=()
declare _hint="start.hint"
declare _paths
declare _basepath="root/devops/cloud"
declare _base="/"
declare _hintmaxdepth=0

    echo "${BASH_VERSION}"

    getDeclared


    

HAS SAME OUTPUT

➜  sometest bash working1.sh                                                                                                 
5.1.16(1)-release
0: BASH=/usr/local/bin/bash

Shellcheck just shows one warning on the x=($v) inside the function, saying to quote to prevent splitting. But I don't see any difference when I do x="($v)" it just puts parens around the result as so:

➜  sometest bash working1.sh                                                                                                 
5.1.16(1)-release
0: (BASH=/usr/local/bin/bash)

What am I missing here? Help! :)

CodePudding user response:

[Why do I get discrepencies between two code snippets?]

Because $v is only the first array element, so there is only one element inside x. If you want to copy an array, you should have used x=("${v[@]}").


Just -d '' and prefer mapfile.

  • Related