# accessing loop variable in a loop [duplicate]

This question already has an answer here:

This is my script:

``````load_1=15231
load_2=20547
load_3=24561
load_4=22874
f4=434

sum_1=`expr \$load_1 + \$f4`
sum_2=`expr \$load_2 + \$f4`
sum_3=`expr \$load_3 + \$f4`
sum_4=`expr \$load_4 + \$f4`

min=\$sum_1
LIST1="1 2 3 4"
for x in \$LIST1
do
if [ \$sum_\$x -lt \$min ]
then
min=\$sum_\$x
f3=\$x
fi
done
echo \$min
echo \$f3
``````

below is the output while executing the script using `bash -x`:

``````+ load_1=15231
+ load_2=20547
+ load_3=24561
+ load_4=22874
+ f4=434
++ expr 15231 + 434
+ sum_1=15665
++ expr 20547 + 434
+ sum_2=20981
++ expr 24561 + 434
+ sum_3=24995
++ expr 22874 + 434
+ sum_4=23308
+ min=15665
+ LIST1='1 2 3 4'
+ for x in '\$LIST1'
+ [[ 1 -lt 15665 ]]
+ min=1
+ f3=1
+ for x in '\$LIST1'
+ [[ 2 -lt 1 ]]
+ for x in '\$LIST1'
+ [[ 3 -lt 1 ]]
+ for x in '\$LIST1'
+ [[ 4 -lt 1 ]]
+ echo 1
1
+ echo 1
1
``````

the value of loop variable 'x' has to be substituted in the test condition variable `sum_x` and then value of `\$sum_x` has to be given to the test condition. But as shown in the output, the value of 'x' is directly taken in the condition. I have tried various combinations of quotes and paranthesis but nothing worked for me. Please help!!

## marked as duplicate by mikeserv, PersianGulf, chaos, G-Man, Stephen KittJun 9 '15 at 21:46

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

• Could you explain what your script is supposed to be doing? As far as I can tell, you are checking whether any of the sums is less than the 1st one and, if so, set `min` to that sum and `f3` to the relevant index. In your example, however, that would never be true and `f3` would never be set. Please edit and explain in words what output you are expecting. – terdon Jun 9 '15 at 12:49

## 4 Answers

Your problem is that `\$sum_\$x` is interpreted as the concatenation of `\$sum_` and `\$x`:

``````~\$ for x in \$LIST1;  do   echo \$sum_\$x;  done
1
2
3
4
``````

Hence your problem. What you want is using

``````~\$ for x in \$LIST1;  do   echo \$((sum_\$x));  done
15665
20981
24995
23308
``````
• @FredtantiniThanks for your solution....it is working is there any way to initialize the values of sum_1 to sum_4 in a loop as below LIST1="1 2 3 4" for j in \$LIST1 do sum_\$j=`expr \$((load_\$j)) + \$f4` done because when i am executing this script, iam getting "command not found error" – Prashanth Jun 9 '15 at 9:59

I don't really understand what your script is supposed to be doing and you haven't told us what language you are writing in. I will therefore assume bash and that you are aware of the fact that the values you have in your question don't make your script do anything very useful.

In general, concatenating strings to get a variable name is both quite cumbersome and unneeded. Just use arrays instead:

``````#!/usr/bin/env bash
load=(15231 20547 24561 22874)
f4=434

for((i=0;i<\${#load[@]};i++))
do
sums[i]=\$((\${load[i]} + \$f4))
done

min=\$((\${sums}))
for((i=1;i<\${#load[@]};i++))
do
if [ "\${sums[i]}" -lt "\$min" ]
then
min="\${sums[i]}"
f3="\$i"
fi
done

printf "%s\n%s" "\$min" "\$f3"
``````
1. a more bash way for what you need:
try this:
``````load_1=15231
load_2=20547
load_3=24561
load_4=22874
f4=434
line=`(set -o posix ; set) | grep load_  | sort -t = -n -k2 | head -1`
min=`echo \$line | cut -d= -f2`
echo \$((min+f4))
echo \$line | cut -d= -f1 | cut -d_ -f2
``````

This results in: ``` 15665 1 ```

if you want to use your code anyway:

1. you can avoid using `LIST1` by `for x in {1..4}`

2. set `f3=1` when you set `min`, otherwise - as in your example - it isn't set

``````load_1=15231
load_2=20547
load_3=24561
load_4=22874
f4=434
min=0
f3=1

for n in 1 2 3 4
do   [ "\$((sum_\$n=load_\$n+f4))" -lt \
"\$((min=min?min:sum_\$n))" ] &&
min=\$((sum_\$n)) f3=\$n
printf '\$%s =\t%d\n' \
"sum_\$n" "\$((sum_\$n))" \
min "\$min" f3 "\$f3"
done
``````

The math expansion will expand the shell variables first. When it does it will arrive at a statement that looks like:

``````sum_ = load_ + f4
``````

...where the brackets represent each iteration in the loop, and which is valid arithmetic syntax because strings represent variable names for integers in a shell arithmetic expansion. It will set those variables in the current shell context even when it is used as an argument to `[ test ]` - so `\$sum_1` is simultaneously set to the value 15231 and compared to `\$min` which is `0`.

But based on your values `\$min` is never adjusted according to `\$sum_\$n` because no value for `\$sum_\$n` is ever less than `\$min`.

### OUTPUT

``````\$sum_1 =    15665
\$min =  15665
\$f3 =   1
\$sum_2 =    20981
\$min =  15665
\$f3 =   1
\$sum_3 =    24995
\$min =  15665
\$f3 =   1
\$sum_4 =    23308
\$min =  15665
\$f3 =   1
``````

In fact, we could put the entire thing in a single math expansion and leave the test out entirely:

``````load_1=15231
load_2=20547
load_3=24561
load_4=22874
f4=434
f3=\$((!(min=0)))
for n in 1 2 3 4
do  echo \\$min = "\$((
min = ( min    >  ( sum_\$n = load_\$n+f4 ) )
? ( sum_\$n + !( f3     = \$n         ) )
: ( min    ?    min    : sum_\$n     )
))"; done
``````

That sets all variables appropriately for every iteration, but only expands to `\$min`'s value each time. It prints:

``````\$min = 15665
\$min = 15665
\$min = 15665
\$min = 15665
``````