How do I iterate over a range of numbers in Bash when the range is given by a variable?
I know I can do this (called \"sequence expression\" in the Bash documentatio
The POSIX way
If you care about portability, use the example from the POSIX standard:
i=2
end=5
while [ $i -le $end ]; do
echo $i
i=$(($i+1))
done
Output:
2
3
4
5
Things which are not POSIX:
(( ))
without dollar, although it is a common extension as mentioned by POSIX itself.[[
. [
is enough here. See also: What is the difference between single and double square brackets in Bash?for ((;;))
seq
(GNU Coreutils){start..end}
, and that cannot work with variables as mentioned by the Bash manual.let i=i+1
: POSIX 7 2. Shell Command Language does not contain the word let
, and it fails on bash --posix
4.3.42the dollar at i=$i+1
might be required, but I'm not sure. POSIX 7 2.6.4 Arithmetic Expansion says:
If the shell variable x contains a value that forms a valid integer constant, optionally including a leading plus or minus sign, then the arithmetic expansions "$((x))" and "$(($x))" shall return the same value.
but reading it literally that does not imply that $((x+1))
expands since x+1
is not a variable.
The seq
method is the simplest, but Bash has built-in arithmetic evaluation.
END=5
for ((i=1;i<=END;i++)); do
echo $i
done
# ==> outputs 1 2 3 4 5 on separate lines
The for ((expr1;expr2;expr3));
construct works just like for (expr1;expr2;expr3)
in C and similar languages, and like other ((expr))
cases, Bash treats them as arithmetic.
If you're doing shell commands and you (like I) have a fetish for pipelining, this one is good:
seq 1 $END | xargs -I {} echo {}
Another layer of indirection:
for i in $(eval echo {1..$END}); do
∶
If you need it prefix than you might like this
for ((i=7;i<=12;i++)); do echo `printf "%2.0d\n" $i |sed "s/ /0/"`;done
that will yield
07
08
09
10
11
12
I know this question is about bash
, but - just for the record - ksh93
is smarter and implements it as expected:
$ ksh -c 'i=5; for x in {1..$i}; do echo "$x"; done'
1
2
3
4
5
$ ksh -c 'echo $KSH_VERSION'
Version JM 93u+ 2012-02-29
$ bash -c 'i=5; for x in {1..$i}; do echo "$x"; done'
{1..5}