How can I make a script to count up by fives?

I was trying to make a very simple bash script to list all of the multiples of five between 375 and 3500 (375, 380, 385…). One thing that I tried and didn’t work is:

for i in {375..3500}
do
        echo $i
        (($i += 5))
done

I gave up after a while and wrote this in BASIC in about 15 seconds:

10 count = 375
20 print count
30 count = count+5
40 if count < 3500 then goto 20

How can I make my BASIC program in a bash script?

Asked By: aswine

||

Using SEQ(1)

for i in $(seq 375 5 3500)
do
    echo $i
done

Or, simply:

seq 375 5 3500
Answered By: Emeric

Alternatively a traditional C-style for loop can be used:

for ((i=375; i<=3500; i+=5)); do
    echo $i
done

This is perhaps less clear than using seq, but it doesn’t spawn any subprocesses. Though since I’m familiar with C, I wouldn’t have any difficulty understanding this, but YMMV.

Answered By: Muzer

Since you use brace expansion anyway, so make use of its feature fully:

echo {375..3500..5}

You can also use this technique to print each number in separate line with optional text by using printf instead of echo, for example:

$ printf "Number %s is generated.n" {375..3500..5}
Number 375 is generated.
Number 380 is generated.
Number 385 is generated.
...

Edit

As pointed out by @kojiro in the comment Mac OS uses bash 3 as the default shell, which doesn’t support increment in sequence expression of brace expansion. You need to upgrade to bash version 4 or use other shell which supports that (e.g. recent zsh).

Answered By: jimmij

While there is, of course, an app for that (seq 375 5 3500), there are various ways of doing this from the commandline. While the fastest and simplest will be just using seq, here are some other options:

for i in {375..3500}; do [[ (($i % 5)) -eq 0 ]] && echo $i; done

i=370; while [ $i -le 3500 ]; do printf "%sn" $((i+=5)); done

perl -le '$i=shift;while($i<=$ARGV[0]){print $i; $i+=5; }' 375 3500
perl -le 'map{print $_ + 5} 370..3495'

awk 'BEGIN{ for(i=375;i<=3500;i+=5){print i}}'
Answered By: terdon

Your for-loop snippet didn’t work as you require for two reasons:

  • (($i += 5)) – here the $i is expanded to the value of i. Thus the expansion will be something like ((375 += 5)), which doesn’t make sense (attempting to assign a literal number to another literal number). This would normally be achieved with ((i += 5)) (no $ to expand the variable)
  • The {375..3500} will be expanded before the first iteration of the loop. It will be the list of numbers 375 376 ... 3499 3500. For each iteration of the loop, i will get assigned to each of these numbers, one-by-one. Thus at the start of each iteration, i will be reassigned to the next value in that list, counting up in steps of 1. The ((i += 5)) effectively does nothing – it does add 5 to i, but then i is just reassigned again at the start of the next iteration.

I think I like the for (( ; ; )) answer best, but here are some alternatives to get you thinking:


Since we’re dealing with multiples of 5, and the {a..b..i} expansion is not supported in bash version 3.2.57(1) (in OS X), then we can do this slightly arcane thing instead:

for i in 375 {38..349}{0,5} 3500; do
    echo $i
done

This demonstrates how bash can be used to create a cartesian product.


I think in general a for loop is the most convenient way to do this, but if you’re interested, you can use a while-loop (a bit closer to your BASIC) program:

count=375
while (( count <= 3500 )); do
    echo $count
    (( count += 5 ))
done
Answered By: Digital Trauma

POSIXly:

i=370
while [ 3500 -gt "$i" ]
do    echo "$((i+=5))"
done

…or…

echo 'for(x=370;x<=3500;x+=5)x' |bc

I dunno why you’d do it any other way. Excepting, of course…

seq 375 5 3500

…or with dc:

echo '370[5+pd3500>p]splpx'|dc
Answered By: mikeserv

If you’re stuck on Bash 3:

echo {375..3500} | tr ' ' 'n' | sed -n 'p;n;n;n;n'

and if you prefer awk:

echo {375..3500} | tr ' ' 'n' | awk '!((NR-1)%5)'

I didn’t know about brace expansion — that is seriously cool.

Answered By: bonh
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.