Shell script "for" loop syntax

UnixSyntaxShell

Unix Problem Overview


I have gotten the following to work:

for i in {2..10}
do
    echo "output: $i"
done

It produces a bunch of lines of output: 2, output: 3, so on.

However, trying to run the following:

max=10
for i in {2..$max}
do
    echo "$i"
done

produces the following:

output: {2..10}

How can I get the compiler to realize it should treat $max as the other end of the array, and not part of a string?

Unix Solutions


Solution 1 - Unix

Brace expansion, {x..y} is performed before other expansions, so you cannot use that for variable length sequences.

Instead, use the seq 2 $max method as user mob stated.

So, for your example it would be:

max=10
for i in `seq 2 $max`
do
    echo "$i"
done

Solution 2 - Unix

Try the arithmetic-expression version of for:

max=10
for (( i=2; i <= $max; ++i ))
do
    echo "$i"
done

This is available in most versions of bash, and should be Bourne shell (sh) compatible also.

Solution 3 - Unix

Step the loop manually:

i=0
max=10
while [ $i -lt $max ]
do
echo "output: $i"
true $(( i++ ))
done

If you don’t have to be totally POSIX, you can use the arithmetic for loop:

max=10
for (( i=0; i < max; i++ )); do echo "output: $i"; done

Or use jot(1) on BSD systems:

for i in $( jot 0 10 ); do echo "output: $i"; done

Solution 4 - Unix

If the seq command available on your system:

for i in `seq 2 $max`
do
  echo "output: $i"
done

If not, then use poor man's seq with perl:

seq=`perl -e "\$,=' ';print 2..$max"`
for i in $seq
do
  echo "output: $i"
done

Watch those quote marks.

Solution 5 - Unix

We can iterate loop like as C programming.

#!/bin/bash
for ((i=1; i<=20; i=i+1))
do 
      echo $i
done

Solution 6 - Unix

There's more than one way to do it.

max=10
for i in `eval "echo {2..$max}"`
do
    echo "$i"
done

Solution 7 - Unix

This is a way:
Bash:

max=10
for i in $(bash -c "echo {2..${max}}"); do echo $i; done

The above Bash way will work for ksh and zsh too, when bash -c is replaced with ksh -c or zsh -c respectively.

Note: for i in {2..${max}}; do echo $i; done works in zsh and ksh.

Solution 8 - Unix

Well, as I didn't have the seq command installed on my system (Mac OS X v10.6.1 (Snow Leopard)), I ended up using a while loop instead:

max=5
i=1

while [ $max -gt $i ]
do
    (stuff)
done

*Shrugs* Whatever works.

Solution 9 - Unix

Here it worked on Mac OS X.

It includes the example of a BSD date, how to increment and decrement the date also:

for ((i=28; i>=6 ; i--));
do
    dat=`date -v-${i}d -j "+%Y%m%d"` 
    echo $dat
done

Solution 10 - Unix

Use:

max=10
for i in `eval echo {2..$max}`
do
    echo $i
done

You need the explicit 'eval' call to reevaluate the {} after variable substitution.

Solution 11 - Unix

These all do {1..8} and should all be POSIX. They also will not break if you put a conditional continue in the loop. The canonical way:

f=
while [ $((f+=1)) -le 8 ]
do
  echo $f
done

Another way:

g=
while
  g=${g}1
  [ ${#g} -le 8 ]
do
  echo ${#g}
done

and another:

set --
while
  set $* .
  [ ${#} -le 8 ]
do
  echo ${#}
done

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioneykanalView Question on Stackoverflow
Solution 1 - UnixwhatsisnameView Answer on Stackoverflow
Solution 2 - Unixsystem PAUSEView Answer on Stackoverflow
Solution 3 - UnixNietzche-jouView Answer on Stackoverflow
Solution 4 - UnixmobView Answer on Stackoverflow
Solution 5 - UnixrashedcsView Answer on Stackoverflow
Solution 6 - UnixephemientView Answer on Stackoverflow
Solution 7 - UnixJahidView Answer on Stackoverflow
Solution 8 - UnixeykanalView Answer on Stackoverflow
Solution 9 - Unixminhas23View Answer on Stackoverflow
Solution 10 - UnixChris DoddView Answer on Stackoverflow
Solution 11 - Unixuser4427511View Answer on Stackoverflow