Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

This script works great and I modified it to increment by 5. My problem is I do not need the last comma at the end and I'm not sure how to remove this.

for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
 echo -n "$j,"
done
share|improve this question

7 Answers 7

up vote 10 down vote accepted

You rarely really need a loop in bash:

echo {0..55..5} | sed 's/ /,/g'
share|improve this answer
    
Thanks I was working on the increment portion in the same format you described, however I was messing up. As for the sed makes sense. –  JeremyA1 Jun 28 at 8:46

On GNU and a few other systems, for this particular problem, just use seq:

seq -s, 0 5 55

That gives the sequence from 0 to 55 (inclusive), separated by a comma.


There are a few pure-bash options, which might be useful if your problem is a bit more complicated than the example suggests. The most standard is just to use an explicit test for whether you're on the last iteration:

for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
 echo -n "$j"
 [ $i -lt 12 ] && echo -n ,
done

Here we only print out the $j every time, and test whether $i is less than 12 (i.e., we're not on the last iteration) before printing the comma.

An alternative is to build up the whole output as a single string:

for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
 ACCUM="$ACCUM$j,"
done
echo "${ACCUM%,}"

Here we make ACCUM hold the same thing you were printing out already, but we don't output anything in the loop itself. You can trim off the comma at the end with ${ACCUM%,}: that expands to the value of ACCUM with anything at the end matching , cut off.

If the seq option works for your use case I'd go with that, though.

share|improve this answer
1  
Note that for ((...)) is ksh93, bash and zsh only. –  Stéphane Chazelas Jul 4 at 7:02

Instead of adding commas everywhere and then removing the last one, here's a potential 'pure bash' solution using the IFS variable with the [*] form of array expansion

a=( {0..55..5} ); (IFS=, ; printf '%s\n' "${a[*]}")
0,5,10,15,20,25,30,35,40,45,50,55

See BashGuide/Arrays for details - including an explanation of the use of the (...) subshell to preserve the parent shell's IFS value.


If you don't want to use the array approach, then you could avoid the external sed command by using the shell's built-in string substitution capabilities, for example (again in bash)

printf -v str '%s,' {0..55..5}; printf '%s\n' "${str%,}"
0,5,10,15,20,25,30,35,40,45,50,55
share|improve this answer

The more sophisticated solutions you've received are better but for the sake of completeness, you could always just remove the final comma with sed:

for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
 echo -n "$j,"
done | sed 's/,$//'
share|improve this answer

For reference, with zsh:

$ echo ${(j(,)):-{0..55..5}}
0,5,10,15,20,25,30,35,40,45,50,55
share|improve this answer

Here is a POSIX compatible solution:

i=-5
until [ $((i=i+5)) -eq 55 ]
    do printf ${i},
done && echo $i

###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55

Alternatively you could manipulate IFS:

 set -- $(echo $((i=0)); until (exit $((i-55))); do echo $((i=i+5)); done)
 IFS=,
 echo "$*"

###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55

But...

unset IFS
printf %s\\n "$@"

###OUTPUT###
0
5
10
15
20
25
30
35
40
45
50
55

All of the increments are still available in $@ and are singly available in $1 - ${12}.

And this one's fun and loop free:

i= ; eval echo $(IFS=0; printf '${i:+,}$((i=i${i:++5}))%s' $(printf %012d))

###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55

With bc and tr:

echo '0;while(a+=5<=55){",";a}'|bc|tr -d \\n

###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55

or just bc and shell...

printf %s $(echo '0;while(a+=5<=55){",";a}'|bc)

###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55

With GNU dc:

dc -e '[pq]sq0[rdn[,]P5+d55=qrdx]dx'

###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55

I like the last the best, but I'm a sucker for an ugly dc script.

share|improve this answer

You simply add a check when you reach the end:

for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
 if [[ $i -ne 12 ]]
 then
   echo -n "$j,"
 else
   echo -n "$j"
 fi
done
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.