Darlyn
Darlyn

Reputation: 4938

loops inside condition shell scripting

Im beginner in shell scripting and im trying to achieve following , if i pass two numbers as argument for example = 0 5 , the console will output 1 2 3 4 5 , but if i pass 5 0 , console should output 5 4 3 2 1 , the first one works nice , but the second one does nothing in my script , it does not throw any arror.

script

if [[ $1 -lt $2 ]]; then
  for((i=$1;i<$2;i++))
  do
    if [[ "$i" -lt $2 ]]; then
      echo -n "$i "
    else 
      echo -n "$i"
    fi
  done
else
  for((i=$2;i>=$1;i--))
  do
    if [[ "$i" -gt $1 ]]; then
      echo -n "$i "
    else 
      echo -n "$i"
    fi
  done
fi

as i said the first condition works - numbers are 0 5 for example but the second when first number is greater than second does not . how can i fix it?

Upvotes: 1

Views: 71

Answers (4)

Charles Duffy
Charles Duffy

Reputation: 295353

There's no need for the nested ifs here -- it's more sensible to determine the test to use and the iteration detection beforehand, and then have only one loop that's always used:

#!/bin/bash

delta=${3:-1} # if $3 is given, treat it as number to increment/decrement by
if (( $1 < $2 )); then
  delta=$(( delta < 0 ? -delta : delta)); cmp=-lt
else
  delta=$(( delta > 0 ? -delta : delta)); cmp=-gt
fi

i=$1
while test "$i" "$cmp" "$2"; do
  printf '%s ' "$i"
  i=$(( i + $delta ))
done
printf '\n'

This has a great deal in common with the existing (excellent) answer by @William Pursell, but adds the ability to provide a skip value (for instance, to count from 0 to 100 by 10s) safely, which using an exact equality check doesn't do.

Upvotes: 1

William Pursell
William Pursell

Reputation: 212238

This will print "1 2 3 4 5" or "4 3 2 1 0" instead of "5 4 3 2 1", but I think that is a more reasonable output. If you want the non-symmetric output, it's easy enough to fix.

#!/bin/bash   

i=$1            
test $2 -gt $1 && op=+ || op=- 
while test $i != $2; do printf "%d " $(( i=$i $op 1)); done  
echo

Upvotes: 3

Andreas Louv
Andreas Louv

Reputation: 47099

You have a logical error in your second for loop:

for((i=$2;i>=$1;i--))
# should have been:
for((i=$1;i>=$2;i--))

If you exterminate your code you will see that $1 will always be bigger or equal than $2 in your else-statement:

if [[ $1 -lt $2 ]]; then
  # ...
else
  # now $1 is equal or bigger than $2

You properly want to change your if-statement as well:

if [[ "$i" -gt $1 ]]; then
# change to $2 because $i will never be bigger than $1
if [[ "$i" -gt $2 ]]; then

When all of this is said you should really consider using an existing tool like seq [fisrt] [increment] last:

seq 1 5 | xargs; # 1 2 3 4 5
seq 5 -1 1 | xargs; # 5 4 3 2 1

Upvotes: 3

glenn jackman
glenn jackman

Reputation: 246774

You can farm out some of the work to external tools:

if (( $1 > $2 )); then
    seq $1 -1 $(($2+1))
else
    seq $(($1+1)) 1 $2
fi | paste -sd " "

Upvotes: 0

Related Questions