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:
- Conditional
[ "$2" "1"] is broken: it's missing the mandatory space before ]
- With that fixed, it'll only work if
$2 expands to a unary test operator such as -n.
- Perhaps you meant
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
- Note that bash considers
do ... and then ... separate statements, hence you often see if ...; then and for ...; do.
- In general, I encourage you to syntax-check your shell code at http://shellcheck.net - it's a great tool for detecting syntax problems.
Note how different rules apply inside (( ... )) compared to elsewhere in bash:
- spaces around the
= in the variable assignment are allowed.
- referencing a variable without the
$ prefix (a++) is allowed.
< performs numerical comparison (whereas inside [[ ... ]] it's lexical) -i.e., it's the more natural equivalent to -lt inside [ ... ] or [[ ... ]].
- several other mathematical and even bit-wise operators are supported
- ...
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.