You are not logged in.
I am trying to set variables by $var=$var in the following nested for loops.
It does not work. Is there anything I can do like that?
#!/bin/bash
aa="bb cc dd ee ff gg"
for i in $aa; do
for ii in BBVAR CCVAR DDVAR EEVAR FFVAR GGVAR; do
# I am trying to set variable like BBVAR=bb for example.
$ii=$i
done
done
echo "$BBVAR" # expecting "bb" here
echo "$CCVAR" # expecting "cc" here
echo "$DDVAR" # expecting "dd" here
echo "$EEVAR" # expecting "ee" here
echo "$FFVAR" # ecpecting "ff" here
echo "$GGVAR" # expecting "gg" here
Last edited by duyinthee (2023-09-21 08:28:27)
Offline
Like this?
var1="hold"
declare $var1="told"
echo $hold
Offline
Do you really want explicit variables for those indexed values? Why not:
#!/bin/bash
aa="bb cc dd ee ff gg"
set -- $aa
echo $1 # outputs "bb"
echo $2 # outputs "cc"
echo $3 # outputs "dd"
Offline
I suspect it's not about $aa, but a general question about dynamically named variables.
Offline
let me paste here my solution for what I am trying. But I want to combine those if...else...fi parts and shorten.
That's why, I am considering for i in; do... done
#!/bin/bash
aa="bb cc dd ee ff gg"
num=1
for i in $aa; do
# for ii in BBVAR CCVAR DDVAR EEVAR FFVAR GGVAR; do
# declare "$ii=$i"
# done
if [[ $((num)) -eq 1 ]]; then
BBVAR=$i
num=$((num+1))
continue
fi
if [[ $((num)) -eq 2 ]]; then
CCVAR=$i
num=$((num+1))
continue
fi
if [[ $((num)) -eq 3 ]]; then
DDVAR=$i
num=$((num+1))
continue
fi
if [[ $((num)) -eq 4 ]]; then
EEVAR=$i
num=$((num+1))
continue
fi
if [[ $((num)) -eq 5 ]]; then
FFVAR=$i
num=$((num+1))
continue
fi
if [[ $((num)) -eq 6 ]]; then
GGVAR=$i
num=$((num+1))
continue
fi
done
echo "$BBVAR"
echo "$CCVAR"
echo "$DDVAR"
echo "$EEVAR"
echo "$FFVAR"
echo "$GGVAR"
What I really want is to set many variables based on a command's outputs.
Last edited by duyinthee (2023-09-19 08:50:31)
Offline
Have you tried the declare thing I posted?
EDIT: I also recommend having a look at "associative array" in bash, like https://linuxhint.com/associative_array_bash/
Last edited by Awebb (2023-09-19 09:56:42)
Offline
Replacing:
$ii=$i
with:
eval "$ii=$i"
will assign a value to all of the xxVAR variables but they will all be assigned the value gg. You have nested loops and the eval statement will be executed 36 times. Each xxVAR variable will be assigned each of the aa values consecutively. The following would work:
#!/bin/bash
declare -A assArray=( [BBVAR]=bb
[CCVAR]=cc
[DDVAR]=dd
[EEVAR]=ee
[FFVAR]=ff
[GGVAR]=gg )
for val in "${!assArray[@]}"; do
eval "$val=${assArray[$val]}"
done
echo "$BBVAR" # expecting "bb" here
echo "$CCVAR" # expecting "cc" here
echo "$DDVAR" # expecting "dd" here
echo "$EEVAR" # expecting "ee" here
echo "$FFVAR" # ecpecting "ff" here
echo "$GGVAR" # expecting "gg" here
Last edited by eda2z (2023-09-19 17:56:05)
Offline
Thanks you all for replies with suggestions. Yes, it works with "declare" and also "eval".
What I do now is this below;
#!/bin/bash
aa="bb cc dd ee ff gg"
IFS=' '
NUM=1
for i in $aa; do
ii=$(echo "BB CC DD EE FF GG" | cut -d ' ' -f "$NUM")
eval $i=$ii # here (declare $i=$ii) is also work
NUM=$((NUM+1))
done
echo $bb
echo $cc
echo $dd
echo $ee
echo $ff
echo $gg
I don't know declare or eval is the right one here.
Offline
Be extremely careful with `eval` because it allows arbitrary code execution, which is especially dangerous if your variables are taken from arbitrary input.
name=BBVAR
value=$(cat evil_file)
eval $name=$value
# Congratulations, your home directory was wiped clean
# The contents of "evil_file" were "bb; rm -rf -- ~/* ~/.*"
I suggest you stick with associative arrays, similar to eda2z's suggestion, which make things a tad easier and safer:
keys=(name age gender balance)
declare -A client
client[name]=Alice
client[age]=25
client[gender]=female
client[balance]=10000
for key in "${keys[@]}"; do
echo key: "$key", value: "${client[$key]}"
done
# Or if you don't want a static key list, you can always do:
for key in "${!client[@]}"; do
echo key: "$key", value: "${client[$key]}"
done
Outputs:
key: name, value: Alice
key: age, value: 25
key: gender, value: female
key: balance, value: 10000
If you absolutely have to reference variable names outside of associative arrays, Bash allows the so-called indirect expansion using the `${!var}` syntax, which expands to the value of the variable whose name is stored in `var`.
age=25
var=age
echo "name: ${var}, value: ${!var}"
Outputs:
name: age, value: 25
For assignment, I think the only (possibly) safe way would be something like this:
declare -- "$name=$value"
Observe that we used `--` to make it impossible for `$name=$value` to be interpreted as an option string in case `$name` starts with a hyphen, and more importantly, we quoted the whole thing to prevent Bash from splitting them into multiple arguments in case they contain any whitespace, which would result in buggy code at best and security exploits at worst.
Offline