accessing loop variable in a loop [duplicate]

This is my script:

f4=434

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:

+ 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!!

• 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

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" 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
f4=434

do
done

min=\$((\${sums}))
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:
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

f4=434
min=0
f3=1

for n in 1 2 3 4
"\$((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:

...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:

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