I run below script:
for (( i=1; i <= 5; i++ ))
do
echo "Random number $i: $RANDOM"
done
I am getting below Error:
Syntax error: Bad for loop variable
why this syntax is not working?
I run below script:
for (( i=1; i <= 5; i++ ))
do
echo "Random number $i: $RANDOM"
done
I am getting below Error:
Syntax error: Bad for loop variable
why this syntax is not working?
As heemayl's answer points out, your construction is a bashism. The standard way of doing what you want would be:
for i in 1 2 3 4 5
do
echo "Random number $i: $RANDOM"
done
Or, more easily expandably:
for i in $(seq 1 5)
do
echo "Random number $i: $RANDOM"
done
(See man seq
for more detail).
Your original script has a (( i=1; i <= 5; i++ ))
construct in for
loop which is a bashism and hence is not being understood by dash
.
In Ubuntu sh
is a symbolic link to dash
, so when you are running
sh ./script.sh
you are basically running
dash ./script.sh
As i mentioned earlier dash
is not understanding the C-like for
loop construct, it is showing the error.
To run the script using bash
, you can:
Run it as as an argument to bash
e.g. bash script.sh
(you don't need to make the script executable)
Make the script executable and from a bash
shell run (from the directory containing the script):
./script.sh
The most portable way is to use a shebang (#!/bin/bash
or preferably #!/usr/bin/env bash
) as the first line of your script. In this way you can run the script from any shell by ./script.sh
, the script will be interpreted as a bash
script and hence will be executed accordingly.
#!/usr/bin/env bash
. Although not 100% of Unix-like systems have env
in /usr/bin
, those that don't are rarer than those with bash
not in bin
. (bin
doesn't have bash
on most systems where bash
is installed but not part of the base system, e.g., FreeBSD.)
– Eliah Kagan
May 10 '15 at 21:16
env
..that will be most portable..
– heemayl
May 10 '15 at 21:29
Thought I'd contribute to the discussion a little bit.
It's already been mentioned that the syntax used in your script is a bashism and hence isn't portable, even though this is C-like and is well understood by those familiar with java and C. From asking my own question on unix.stackexchange.com , I've also learned that syntax such as for i in $(seq 1 5)
generates a set of numbers first and then iterates , which can be wasteful if you have a very large set.
A better way to simulate C-like behavior, which is portable, is to use while
loop, with a variable that can be incremented. For instance,
#!/bin/sh
number=0
while [ "$number" -lt 10 ]
do
printf "\t%d" "$number"
number=`expr $number + 1 `
done
This works with bash, dash, zsh, ksh, mksh . . . or basically any shell related to bourne shell. In fact, I've a Unix System V book from like 1995, and I've tested their example for bourne shell and it still works. The behaviour is also that of C-like for loop: you have initial condition, testing condition within while [ . . .]
, and update condition at the end.
csh and tcsh have syntax closer to C language, but its not portable to other shells, and they're not recommended to be used in scripting.
Addition:
Concerning portability of $RANDOM, according to this page on ubuntu wiki, with dash random number generation should rely on using /dev/urandom
command time -f '%E' dash -c '...'
as the test harness, for i in $(seq 1 100000000); do test $i -eq 1000 && break; done
took 0:48.37, but i=1; while [ $i -lt 100000000 ]; do test $i -eq 1000 && break; i=$(expr $i + 1); done
took 0:02.23.
– Eliah Kagan
May 10 '15 at 21:13
i
or have a file named "i" in your WD? – s3lph May 10 '15 at 18:15sh
..the syntax is correct forbash
..how are you running it? – heemayl May 10 '15 at 18:15#! /bin/bash
at the beginning? – muru May 10 '15 at 18:21