for loop using {1..$t}

I read here: Bash For Loop Examples
that I should not use seq , instead use {1..10}

I am not getting this to work

old code

#!/bin/bash
t=$(cat /var/bin/servers | wc -l)
for c in $(seq 1 $t)
        do
                SERVER[$c]=$(awk 'NR==C { print $2 }' C="$c" /var/bin/servers)
        done

new code not working

#!/bin/bash
t=$(cat /var/bin/servers | wc -l)
for c in {1..$t}
        do
                SERVER[$c]=$(awk 'NR==C { print $2 }' C="$c" /var/bin/servers)
        done

This give error like this error token is "{1..8}"
{1..8} seems to be the correct replacement for $t

also tested this for c in {1..${t}} , not working

This works fine for c in {1..8} , but I need the variable option.

That's useless use of cat , for and wc -l .

You can directly do like this..:slight_smile:

while read line
do
let ++count
SERVER[$count]=$(echo "$line" | awk '{ print $2 }')
done<file

Hope this helps:)

1 Like

Check your bash version..it should be > version 3.0+

Try:

#!/bin/bash
i=0
while read x srv x
do
  SERVER[i++]=srv
done < file

--
You cannot use a variable inside a { list }

while read does work fine. :slight_smile:

GNU bash, version 4.2.8(1)-release (i686-pc-linux-gnu)
As I told in my first post for i in {1..10} works.

It should be possible to use variable in for loops too.

You can use variables in a for loop like this:

for (( c=1; c<=t; c++ )); do
1 Like

You can use variables in for loops, but not inside of a {}. Someone else can probably do a better job of explaining this, but the bottom line is it has to do with the order in which the shell interprets what you're putting into it. As I recall (and to be honest, I usually just learn how things work, not why, so you should probably look this up...) the reason is that expanding the {} is the very first thing the shell does, BEFORE it translates the variable into it's value. So, if you're trying to do:

(

15:45:24\[root@DeCoBoxOmega)
[~]$ x=5

(15:47:46\[root@DeCoBoxOmega)
[~]$ for i in {1..$x};do echo $i;done

What the shell is actually doing is for i in the literal expression {1..$x} because $x doesn't mean anything yet.

It won't and never will.

You've got the wrong idea anyway, use a for-loop.

for ((X=0; X<10; X++))
do
...
done

In other shells you would do

X=0

while [ $X -lt 10 ]
do
        let X=X+1
done

You should never use seq or {...} in open-ended loops.

To use the notion {1..$t}, you need to "eval" it. In this case, you can also do

mapfile -O 1 SERVER <<EOF
$(awk '{print $2}' input-file
EOF

Working solution with eval , but I think I stick to the while solution.

#!/bin/bash
t=10
eval for I in {1..$t}\
\;do\
echo \$I\
\;done

mapfile works fine too :slight_smile: but not included in BusyBox :frowning:
but was missing a )
Correct $(awk '{print $2}' input-file)

---------- Post updated at 05:42 PM ---------- Previous update was at 10:51 AM ----------

.
.
Another good solution found.

{ IFS=$'\n' SERVER=("" $(awk '{print $2}' /var/bin/servers)); }

or written like this:

{ IFS=$'\n' 
    SERVER=("" $(awk '{print $2}' /var/bin/servers))
 }

The "" is added to get value in to array #1 and not #0 as default start.

Using eval is even worse. eval is inefficient and a security hole. Use a for-loop or while-loop; these don't need to calculate all numbers from 1 to N before beginning the loop, unlike {1...10000000000}

for ((X=0; X<10; X++))
do
...
done