Reputation: 175
This is my bash scripting code so I want to know How to Rewrite the below Bash script using a “for” loop instead of the “while” loop.
#!/bin/bash
if [ $# -gt 0 ]; then
a=0;
if [ -f RandNos ]; then
rm RandNos;
fi
while [ $a -lt $1 ]
do
a='expr $a + 1';
myrand=$RANDOM;
if [ "$2" "1"]; then
echo "No. $a ==> $myrand";
fi
echo $myrand>>RandNos
done
else
echo "please use with an argument..."
fi
Thanks.
Upvotes: 0
Views: 391
Reputation: 21
if [ $# -gt 0 ]; then
a=0;
if [ -f RandNos ]; then
rm RandNos;
fi
for (( i=$a; i<$1; i++ ))
do
myrand=$RANDOM;
if [ "$2" = "1" ]; then
echo "No. $a ==> $myrand";
fi
echo $myrand >> RandNos
done
else
echo "please use with an argument..."
fi
Upvotes: 0
Reputation: 476544
Simply rewriting it with a for
loop results in:
#!/bin/bash
if [ $# -gt 0 ]; then
if [ -f RandNos ]; then
rm RandNos;
fi
lim=$(expr $1 - 1)
as=$(seq 0 $lim)
for a in $as
do
a='expr $a + 1';
myrand=$RANDOM;
if [ "$2" "1"]; then # <- Caveat: conditional is BROKEN
echo "No. $a ==> $myrand";
fi
echo $myrand>>RandNos
done
else
echo "please use with an argument..."
fi
But there are several things wrong with the script anyhow. Like the last if
statement.
Upvotes: 1
Reputation: 437208
The short of it: for counter-based loops, use the C-like form of the for
loop:
for (( a = 0; a < $1; a++ )); do
# ... use $a
done
(This replaces while [ $a -lt $1 ]; do a='expr $a + 1' ...; done
.)
See below for more on the rules that apply inside (( ... ))
.
As for the rest of your code:
[ "$2" "1"]
is broken: it's missing the mandatory space before ]
$2
expands to a unary test operator such as -n
.if [[ -z $myrand ]]; then
, to check if $RANDOM
resulted in a nonempty string?a='expr $a + 1'
- which you don't need anymore with the for
loop - doesn't actually invoke expr
, because you're using single quotes - you'd need backticks (`) instead, or, preferably, the modern equivalent: $(expr $a + 1)
. However, with arithmetic evaluation, this could be simplified to (( ++a ))
.
[ ... ]
conditionals work in bash, but they're provided for POSIX compatibility - use [[ ... ]]
as the bash-specific alternative, which is more robust, has more features, and is faster.
bash statements only need terminating with ;
if you place multiple on a single line
do ...
and then ...
separate statements, hence you often see if ...; then
and for ...; do
.Note how different rules apply inside (( ... ))
compared to elsewhere in bash
:
=
in the variable assignment are allowed.$
prefix (a++
) is allowed.<
performs numerical comparison (whereas inside [[ ... ]]
it's lexical) -i.e., it's the more natural equivalent to -lt
inside [ ... ]
or [[ ... ]]
.All these different rules apply when bash operates in an arithmetic context, which applies to (( ... ))
, $(( ... ))
, array subscripts, and other cases.
For all the rules, run man bash
and read the ARITHMETIC EVALUATION
section.
Upvotes: 4
Reputation: 2541
Several things can be improved:
#!/bin/bash
if (( $# )); then # anything but 0 is true
rm -f RandNos # remove if existing, otherwise fail silently
for ((a=0; a<$1; a++)); do
myrand=$RANDOM
# what is the intention here?
(( $2 > 1 )) && echo "No. $a ==> $myrand"
echo "$myrand" >> RandNos
done
else
echo "please use with an argument..."
fi
not sure what your intention was with the [ "$2" "1" ] expression. it is probably not what I made from it.
for ((a=1; a<=$1; a++)); do
may reflect your intended logic better, as you use $a for output only after incrementing it. as pointed out and corrected by @mklement0
Upvotes: 1
Reputation: 5765
if [ $# -lt 1 ];then
echo "First argument must be number".
exit 1;
fi
for a in `seq $1`
do
...
done
Upvotes: 1