Form a sequence of integers at specified interval in bash - bash

I create a sequence with interval 1 using {0..4} syntax alright:
$ for i in {0..4}; do echo $i; done
0
1
2
3
4
However, when I set interval explicitly at 2 using conventional syntax {0..4..2}, it doesn't work:
$ for i in {0..4..2}; do echo $i; done
{0..4..2}
And the expected output should be:
0
2
4
My bash version:
$ echo ${BASH_VERSION}
3.2.25(1)-release
Any feedback is appreciated!

You could use the syntax:
$ for ((i=0; i<=4; i+=2)); do echo $i; done

$ for i in `seq 0 2 4`; do echo $i; done

Related

linux bash script error

when I try to run this script
for ((i=1; i<=5; i++))
do
for ((j=1; j<=5; j++))
do
echo –n $i
done
echo " "
done
I get this error:
syntax error near unexpected token '(('
for ((j=1; j<=5; j++))"
It appears you're running this with an interpreter that is not bash. I've indented your code, but it worked just fine without indentation too.
$ cat test.bash
for ((i=1; i<=5; i++))
do
for ((j=1; j<=5; j++))
do
echo –n $i
done
echo " "
done
$ /bin/sh test.bash
/tmp/test.bash: 1: Syntax error: Bad for loop variable
$ echo $BASH_VERSION
5.0.11(1)-release
$ bash test.bash
–n 1
–n 1
–n 1
–n 1
–n 1
–n 2
–n 2
…
As you can see, echo -n is not reliable. Change that line to printf %s $i to resolve that and your output will become:
11111
22222
33333
44444
55555
If you are invoking it with bash, perhaps your bash version is too old? You can use for i in {1..5} for something more compatible (but not valid POSIX) or you could use for i in 1 2 3 4 5 for full POSIX compatibility. If you have GNU coreutils, you could do for i in $(seq 5) instead (see man seq).
To better approach your intended logic, you could also consider a while loop:
i=0
while [ $((++i)) -le 5 ]
do
j=0
while [ $((++j)) -le 5 ]
do
printf %s $i
done
echo " "
done
This initializes i to zero before a while loop, then increments it in the test condition when comparing it to five; the first loop's first iteration increments i to 1, finds that it is indeed less than or equal (-le) to 5, and therefore continues.
(I'm using a $((…)) arithmetic expression and ++i inside it since the more common i++ would return the value of i before it is incremented while ++i returns the value of i after it is incremented.)

keep expanding a bash variable

imagine we have n months, here say n=3
I would like to keep adding integer 1, 2, 3 into a shell variable called $test:
so when we do
cat $test
it will return
1 2 3
Any idea?
Just find a solution:
for ((i=1;i<=3; i++));
do
test1="${i}"
test+="$test1 "
done
$ n=3
$ for((i=1; i<=n; i++)) do test="${test} $i"; done
$ echo "$test"
1 2 3

Is it possible to use a variable in for syntax in bash?

I wonder If it is possible to write "for i in {n..k}" loop with a variable.
For example;
for i in {1..5}; do
echo $i
done
This outputs
1
2
3
4
5
On the other hands
var=5
for i in {1..$var}; do
echo $i
done
prints
{1..5}
How can I make second code run as same as first one?
p.s. I know there is lots of way to create a loop by using a variable but I wanted to ask specifically about this syntax.
It is not possible to use variables in the {N..M} syntax. Instead, what you can do is use seq:
$ var=5
$ for i in $(seq 1 $var) ; do echo "$i"; done
1
2
3
4
5
Or...
$ start=3
$ end=8
$ for i in $(seq $start $end) ; do echo $i; done
3
4
5
6
7
8
While seq is fine, it can cause problems if the value of $var is very large, as the entire list of values needs to be generated, which can cause problems if the resulting command line is too long. bash also has a C-style for loop which doesn't explicitly generate the list:
for ((i=1; i<=$var; i++)); do
echo "$i"
done
(This applies to constant sequences as well, since {1..10000000} would also generate a very large list which could overflow the command line.)
You can use eval for this:
$ num=5
$ for i in $(eval echo {1..$num}); do echo $i; done
1
2
3
4
5
Please read drawbacks of eval before using.

Sequence expression in bash

I'm used to used the following feature of bash :
for i in ${1..23} ; do echo $i ; done
This doesn't generalize. For instance, replacing 23 by even $p does not work. As the documentation says, this is a purely syntactic feature.
What would you replace this with ?
Note : Of course, this could be done using a while and an auxiliary variable, but this is not what i'm looking for, even if it works. I'm failing back to this actually.
You could use the seq tool to achieve the effect, I don't know if that's okay for your use case
~$ P=3 && for i in `seq 1 $P`; do echo $i; done
1
2
3
or litb's suggestion
~$ P=3 && for ((i=1;i<=$P;i++)); do echo $i; done
1
2
3
If you have it available, the seq command can do similar. Your example might then be:
p=23
for i in `seq 1 $p`
do
echo $i
done
On linux, there is a seq command (unfortunately it's missing in OS X).
#!/bin/bash
p=23
for i in `seq 1 $p`;
do
echo $i
done
OS X workaround: http://scruss.com/blog/2008/02/08/seq-for-os-x/comment-page-1/
$ p=18
$ a='{1..$p}'
$ for num in $( eval echo $(eval echo $a) ); do echo $num; done

Bourne Shell For i in (seq)

I want to write a loop in Bourne shell which iterates a specific set of numbers. Normally I would use seq:
for i in `seq 1 10 15 20`
#do stuff
loop
But seemingly on this Solaris box seq does not exist. Can anyone help by providing another solution to iterating a list of numbers?
try
for i in 1 10 15 20
do
echo "do something with $i"
done
else if you have recent Solaris, there is bash 3 at least. for example this give range from 1 to 10 and 15 to 20
for i in {1..10} {15..20}
do
echo "$i"
done
OR use tool like nawk
for i in `nawk 'BEGIN{ for(i=1;i<=10;i++) print i}'`
do
echo $i
done
OR even the while loop
while [ "$s" -lt 10 ]; do s=`echo $s+1|bc`; echo $s; done
You can emulate seq with dc:
For instance:
seq 0 5 120
is rewritten as:
dc -e '0 5 120 1+stsisb[pli+dlt>a]salblax'
Another variation using bc:
for i in $(echo "for (i=0;i<=3;i++) i"|bc); do echo "$i"; done
For the Bourne shell, you'll probably have to use backticks, but avoid them if you can:
for i in `echo "for (i=0;i<=3;i++) i"|bc`; do echo "$i"; done
#!/bin/sh
for i in $(seq 1 10); do
echo $i
done
I find that this works, albeit ugly as sin:
for i in `echo X \n Y \n Z ` ...
for i in `seq 1 5 20`; do echo $i; done
Result:
5
10
15
20
$ man seq
SEQ(1) User Commands SEQ(1)
NAME
seq - print a sequence of numbers
SYNOPSIS
seq [OPTION]... LAST
seq [OPTION]... FIRST LAST
seq [OPTION]... FIRST INCREMENT LAST

Resources