Calculating a loop size in bash script gives back different output than writing the size hard coded [duplicate] - bash

This question already has answers here:
How do I iterate over a range of numbers defined by variables in Bash?
(20 answers)
Closed 5 years ago.
Is it possible to do something like this:
start=1
end=10
echo {$start..$end}
# Ouput: {1..10}
# Expected: 1 2 3 ... 10 (echo {1..10})

In bash, brace expansion happens before variable expansion, so this is not directly possible.
Instead, use an arithmetic for loop:
start=1
end=10
for ((i=start; i<=end; i++))
do
echo "i: $i"
done
OUTPUT
i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
i: 8
i: 9
i: 10

You should consider using seq(1). You can also use eval:
eval echo {$start..$end}
And here is seq
seq -s' ' $start $end

You have to use eval:
eval echo {$start..$end}

If you don't have seq, you might want to stick with a plain for loop
for (( i=start; i<=end; i++ )); do printf "%d " $i; done; echo ""

I normally just do this:
echo `seq $start $end`

Are you positive it has be BASH? ZSH handles this the way you want. This won't work in BASH because brace expansion happens before any other expansion type, such as variable expansion. So you will need to use an alternative method.
Any particular reason you need to combine brace and variable expansion? Perhaps a different approach to your problem will obviate the need for this.

use -s
ex:
seq -s ' ' 1 10
output: 1 2 3 4 5 6 7 8 9 10

Related

For loop over sequence of large numbers in Bash [duplicate]

This question already has answers here:
Bash command line and input limit
(4 answers)
Closed 4 years ago.
In a Bash script I am using a simple for loop, that looks like:
for i in $(seq 1 1 500); do
echo $i
done
This for loop works fine. However, when I would like to use a sequence of larger numbers (e.g. 10^8 to 10^12), the loop won't seem to start.
for i in $(seq 100000000 1 1000000000000); do
echo $i
done
I cannot imagine, that these numbers are too large to handle. So my question: am I mistaken? Or might there be another problem?
The problem is that $(seq ...) is expanded into a list of words before the loop is executed. So your initial command is something like:
for i in 100000000 100000001 100000002 # all the way up to 1000000000000!
The result is much too long, which is what causes the error.
One possible solution would be to use a different style of loop:
for (( i = 100000000; i <= 1000000000000; i++ )) do
echo "$i"
done
This "C-style" construct uses a termination condition, rather than iterating over a literal list of words.
Portable style, for POSIX shells:
i=100000000
while [ $i -le 1000000000000 ]; do
echo "$i"
i=$(( i + 1 ))
done

Brace expansion of {1..$n} [duplicate]

This question already has answers here:
Brace expansion with a Bash variable - {0..$foo}
(5 answers)
Closed 4 years ago.
I am trying to loop from 1 to n where n is from user input.
If I do:
read n
echo {1..$n}
I get this output for the input 5
{1..5}
How do I make it expand to
1 2 3 4 5
Keep it simple by trying to do it with a for loop as follows.
echo "enter number..."
read n
for((i=1;i<=n;i++)); do
echo "$i"
done
Or use seq with for loop as follows too.
echo "Enter number:"
read howmany
for i in $(seq 1 $howmany); do
echo "$i";
done
Curly braces don't support variables in bash, though eval could be used but it is evil and have loopholes, why so see this link carefully http://mywiki.wooledge.org/BashFAQ/048

How to use eval for a variable inside a for in using Bash?

When I try doing this:
a={0..10}
for i in $a
do
echo $i
done
The output is just: {0..10}
printf -v a "%d " {0..10}
for i in $a
do
echo $i
done
Output:
0
1
2
3
4
5
6
7
8
9
10
This is one of many situations when the traditional tool, seq, is more useful than bash's brace notation:
a=$(seq 0 10)
for i in $a
do
echo $i
done
The above produces:
0
1
2
3
4
5
6
7
8
9
10
An additional advantage of seq is that it works with variables, something that bash's braces won't do. For example:
$ count=5
$ seq 0 $count
0
1
2
3
4
5
Contrast the above with:
$ echo {0..$count}
{0..5}
The above failed because bash's brace notation does not accept variables for arguments.
Mac OSX
seq is available on OSX for versions 10.8+ and maybe also 10.7. On older versions, the similar, but not identical, BSD tool jot can be used instead.
You can use:
for i in $(eval "echo $a"); do echo $i; done
0
1
2
3
4
5
6
7
8
9
10
But better (safer) than eval alternative in BASH is this arithmetic direecitve:
for ((i=0; i<=10; i++)); do echo $i; done
Your code will work if you do
a=$(echo {0..10})
Instead of a={0..10}, which will be interpreted as a='{0..10}' literally.

how to set variable for bash loop array [duplicate]

This question already has answers here:
Is it possible to use a variable in for syntax in bash?
(3 answers)
Closed 8 years ago.
I would like to have a bash loop function like below, with decreasing sequency:
for i in {8..2}
do
...
done
And the 8 and 2 can be set as a variable, like:
start=$1
end=$2
for i in {$start..$end}
do
...
done
But seem this dose not work. How can I do this?
Thanks for all the quick answers, later I found the answer here.
descending loop with variable bash
solution:
start=$1
end=$2
for i in `seq $start -1 $end`
do
...
done
Thanks~
$ start=8; end=2; for ((i = start; i >= end; i--)); do echo "${i}"; done
8
7
6
5
4
3
2
Nope. But here is a workaround
start=$1
end=$2
for i in $(seq $start $end)
do
...
done
You can't use variable substitution there since the {n..m} is already one.
Try using seq:
for i in `seq $start $end`
do
...
done
Alternatively you could do a while loop incrementing the loop variable by manually:
i=$start
while [ $i -lt $end ]; do
...
: $[i++]
done
Although with while you have to be aware if $start is smaller or greater than $end

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.

Resources