arraysbashsubshellcommand-substitution

modify array with command substitution


Im trying to modify array to manage some functionality. I want to access the array lst from the subshell or use somtheing that isnt command substitution for catching the function output.

I have changed the code for better understanding.

#!/bin/bash

lst=()


function fun(){
   match=0
   string="$1"
   for x in "${lst[@]}"; do
      if [[ "$x" = "$string" ]]; then
         match=1
         break
      fi
   done
   if [[ $match -eq 0 ]]; then
      lst+=("$string $2")
      echo "$1"
   else
      echo "$string already called"
   fi   
   
}




echo ================================= TEST 2.1 =================================

echo "${lst[@]}"
res="$( fun "test" "1")" # first call 
echo "$res" - wannted output: test
echo "${lst[@]}"

echo "${lst[@]}"
res="$( fun "test" "**2**")" # secound call 
echo "$res" - wannted output: test
echo "${lst[@]}"

echo "${lst[@]}"
res="$( fun "test" "**2**")" # third call 
echo "$res" - wannted output: test already called
echo "${lst[@]}"

but command subtition opens new sub shell so i cannot access the array.

any ideas?


Here's what is hopefully a clearer example with the obvious syntax issues fixed:

$ cat tst.sh
#!/usr/bin/env bash

fun() {
   local -n arr=$1
   local str=$2

   echo 'done'

   arr[0]="$str"
}

printf -- '-------\nNo subshell:\n'
lst=( 'something' )
declare -p lst
fun lst 'foo'
declare -p lst

printf -- '-------\nWith subshell:\n'
lst=( 'something' )
declare -p lst
rec=$( fun lst 'foo' )
echo "$rec"
declare -p lst

$ ./tst.sh
-------
No subshell:
declare -a lst=([0]="something")
done
declare -a lst=([0]="foo")
-------
With subshell:
declare -a lst=([0]="something")
done
declare -a lst=([0]="something")

Solution

  • Consider not using a subshell and instead passing the rec variable to be populated by reference:

    $ cat tst.sh
    #!/usr/bin/env bash
    
    fun() {
       local -n arr=$1
       local str=$2
       local -n rslt=$3
    
       rslt='done'
    
       arr[0]="$str"
    }
    
    lst=( 'something' )
    declare -p lst
    fun lst 'foo' rec
    echo "$rec"
    declare -p lst
    

    $ ./tst.sh
    declare -a lst=([0]="something")
    done
    declare -a lst=([0]="foo")
    

    Alternatively, see https://unix.stackexchange.com/q/334543/133219 or just google "bash assign variable to output of function without subshell"