2

I want to assign the value of an array dynamically, and when I change the variable the array changes automatically.

var=5  
arr=( $\[$var-1\] $var $\[$var+1\] )  
echo ${arr\[@\]}  
var=10  
echo ${arr\[@\]}

result

4 5 6
4 5 6 

I wanted

4 5 6 
9 10 11
4
  • 2
    Shell arrays do not work this way. In fact, what language do you know that works this way? Commented Dec 28, 2022 at 14:59
  • 3
    Variables just don't work like that. What you can do is instead of assigning var=10 directly, write a function which assigns to var and updates the array. Commented Dec 28, 2022 at 15:00
  • 1
    Do you really have all those backslashes in your code, or did the SO Stacks editor add them? Commented Dec 28, 2022 at 15:44
  • I don't see why this should be closed. The man is asking a valid question. adamfingol: Just use a language that has support for references / pointers. Declare an array of pointers and forget about doing that in bash - there is no need for it in shell scripting, it's too advanced. That may sound condescending, but shell scripting is supposed to be simple. There weren't even any associative arrays in bash for ages (20 years) after the initial release. Commented Jan 6, 2023 at 9:36

3 Answers 3

2

Try something like this:

v1=abc
v2=efd
v3=ghj

arr=( v1 v2 v3 )

for i in ${arr[@]}; { echo ${!i}; }
abc
efd
ghj

Now lets change values of those vars:

v1=123
v2=456
v3=789

$ for i in ${arr[@]}; { echo ${!i}; } 
123
456
789
Sign up to request clarification or add additional context in comments.

7 Comments

Where is the documentation for this loop syntax?
It's an undocumented hack for backwards compatibility. I don't recommend it. c.f. this post - but thanks for pointing it out so I'll know next time I see it, lol... the above works fine with standard syntax using do/done.
@PaulHodges it's here indirect expansion
@Ivan Wow, I didn't know there was a shorthand like that in bash. Oh man... so many times have I typed ; do .. done and thought to myself with despair what kludgy syntax... I've even considered switching to zsh because of this tiny specific feature! You are a true jedi! AND this was answered on my BIRTHDAY! The stars have a aligned :D Aquarius is in the seventh house! This is a sign. hahahah
Happy birthday @ЯрославРахматуллин!) Yes it's pretty handy but as @PaulHodges pointed here it won't work in while/until loops unfortunately.
|
1

Elaborating Ivan's trick and applying get/set "method"-style functions -

[P2759474@sdp-bastion ~]$ cat tst
#! /bin/bash

arr=( v1 v2 v3 )
v1(){ (($1))&& var=$(($1+1)); echo $((var-1)); }
v2(){ (($1))&& var=$1;        echo $var;       }
v3(){ (($1))&& var=$(($1-1)); echo $((var+1)); }

var=5
for i in ${arr[@]}; { printf "%s=" $i; $i; }

v1 14
for i in ${arr[@]}; { printf "%s=" $i; $i; }

[P2759474@sdp-bastion ~]$ ./tst
v1=4
v2=5
v3=6
14
v1=14
v2=15
v3=16

Comments

0

While such automatic updates are perfectly common in spreadsheet applications, Bash doesn’t work that way. If you want to recalculate a few values based on formulas, you have to explicitly tell Bash to do so. The example below generates the outputs that you expect and defines a function called recalculate that you need to call after changes to the formulas or the formulas’ input variables. The rest of the trick is based around how integer evaluation works in Bash.

recalculate() {
  local -n source="$1" target="$2"
  target=("${source[@]}")
}

formulas=('var - 1' 'var' 'var + 1')
declare -ai arr

var=5
recalculate formulas arr
echo "${arr[@]}"          # 4 5 6

var=10
recalculate formulas arr
echo "${arr[@]}"          # 9 10 11

(It would be awesome if Bash had an additional pseudo-signal for the trap command, say assignment, which could work like trap 'echo "variable ${1} set to ${!1}"' assignment, but AFAIK, there is no such functionality (plus no separate argument handling in trap); hence the strikethrough. Without that kind of functionality, a function like recalculate might be the closest you can get to the updates you asked for.)

A slightly more elaborate version of recalculate could also (1) handle sparse arrays of formulas correctly, i.e. guarantee to store results under the same indices under which the corresponding formulas were found, and (2) introduce a “reserved” variable name, say index, which can occur in the formulas with an obvious meaning. Just for fun, “because we can”:

recalculate() {
  local -n source="$1" target="$2"
  local -i index
  target=()
  for index in "${!source[@]}"; do
    target[index]="${source[index]}"
  done
}

formulas[1]='index * var - 1'
formulas[3]='index * var'
formulas[5]='index * var + 1'
declare -ai arr

var=5
recalculate formulas arr
echo "${arr[@]@A}"  # declare -ai arr=([1]="4" [3]="15" [5]="26")

var=10
recalculate formulas arr
echo "${arr[@]@A}"  # declare -ai arr=([1]="9" [3]="30" [5]="51")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.