Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Bash Script Variable Scope inside Function

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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! 🙂

>Solution :

[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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading