1

i have a a couple of variables with a number in its names. e.g

SERVER_IP48_SUBNET
..
SERVER_IP60_SUBNET

And an additional variable

SERVER_IP

Im trying to expand/concatenate them in the following way:

ALLIPs=${SERVER_IP}
  for i in {48..64}; do
    ALLIPs=${ALLIPs},${SERVER_IP${i}_SUBNET}
  done

as you can imagine this script fails saying: Wrong substitution

Does anybody of you know a good solution for this problem? Thanks so far

FlorFlippi
  • 21
  • 1

3 Answers3

3

Use a nameref with bash version 4.3 +

ALLIPs=${SERVER_IP}

for i in {48..64}; do
    declare -n tmp="SERVER_IP${i}_SUBNET"
    ALLIPs+=",$tmp"
done

But you should really be using an array in the first place:

server_ip=0.0.0.0
subnet_ip=(
    [48]=1.1.1.1
    [49]=2.2.2.2
    # ...
    [64]=16.16.16.16
)

all_ips=( "$server_ip" )
for i in {48..64}; do
    all_ips+=( "${subnet_ip[i]}" )
done

(
  IFS=,
  echo "ALLIPs = ${all_ips[*]}"
)
  • Get out of the habit of using ALLCAPS variable names, leave those as reserved by the shell. One day you'll write PATH=something and then wonder why your script is broken.

I just noticed, if you just want a to join the IP addresses with commas, and you're using an array, you don't need a loop at all:

all_ips=$(
  IFS=,
  set -- "$server_ip" "${subnet_ip[@]}"
  echo "$*"
)
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • 1
    `declare -n tmp; for tmp in SERVER_IP{48..64}_SUBNET; do ALLIPs+=",$tmp"; done` would be more idiomatic. And while declaring the array, `subnet_ip=([48]=1.1.1.1 2.2.2.2)` is the same as `subnet_ip=([48]=1.1.1.1 [49]=2.2.2.2)` but less stuffy. – oguz ismail Dec 13 '20 at 06:05
1

You can use ${!varprefix@} or ${!varprefix*} to expand to all variables with that common prefix (the difference is the same as $@ and $*):

SERVER_IP48_SUBNET=48sub
SERVER_IP49_SUBNET=49sub
SERVER_IP50_SUBNET=50sub

SERVER_IP=1.2.3.4

# set this as empty since !SERVER_IP@ also matches SERVER_IP
ALLIPS=""
for var in "${!SERVER_IP@}"; do
  ALLIPS=$ALLIPS,${!var}
done

This would probably be more practical if you could invert the names like this, since we can only match prefixes:

SERVER_IP_SUBNET_48=48sub
SERVER_IP_SUBNET_49=49sub
SERVER_IP_SUBNET_50=50sub

SERVER_IP=1.2.3.4

ALLIPS=$SERVER_IP
for var in "${!SERVER_IP_SUBNET_@}"; do
  ALLIPS=$ALLIPS,${!var}
done

More info on this feature in the bash manual.

Leonardo Dagnino
  • 2,914
  • 7
  • 28
0

One idea:

SERVER_IP48_SUBNET=48sub
SERVER_IP49_SUBNET=49sub
SERVER_IP50_SUBNET=50sub

SERVER_IP=1.2.3.4

ALLIPs=${SERVER_IP}

for i in {48..50}
do
    tmpvar="SERVER_IP${i}_SUBNET"      # build the variable name
    ALLIPs="${ALLIPs},${!tmpvar}"      # indirect variable reference via tmpvar
done

echo "ALLIPs = $ALLIPs}"

This generates:

ALLIPs = 1.2.3.4,48sub,49sub,50sub
markp-fuso
  • 28,790
  • 4
  • 16
  • 36