code placement

I'm sorry if something like this has already been posted, but I didn't find anything like it.

I'm using ksh The code that I've come up with will initially print what I want, but will then keep repeating the second number. I'm just trying to teach myself and can't seem to find the code to work. Basically, when you enter a number at the command line, it should print that number and each number after it, but not 0. See the attachment for what I have.

#num=$1
#echo $num
while [ "$1" -gt 0 ]; do
 echo $num
 ((num=$1-1))
done

So I assume $1 is a positive number... but the value of $1 doesn't change, so the loop is going to loop forever! Plus that syntax for substracting one from $num won't work. Try this:

num=$1
while [ $num -gt 0 ]; do
 echo $num
 num=`expr $num - 1`
done

Yes, $1 is supposed to be a positive number. I inserted your code that you gave me but it gives me an error about not having a command argument. I tested it with Countdown 8, it would print out the 8 then tell me I need a command argument. I appreciate your help. Back to the books and trying new things. Thank you again!

When I use the code exactly as below, I get the numbers 1 to 8, each printing on their own line, in decreasing order. Does it tell you anything else in that error? Post it exactly as you see it.

if [ "$1" ]
then
num=$1
while [ $num -gt 0 ]; do
 echo $num
 num=`expr $num - 1`
done
else
 echo You did it wrong
fi

That syntax will work fine in most shells. It was introduced in ksh. It is now in most modern shells including bash.

((num=num-1))
is actually much better than:
num=`expr $num - 1`
unless your shell happens to have expr as a builtin.

My command line: /Practice>Countdown 8
Output: 8
Countdown[6]: $num: unknown test operator

this is what it says when executed

Thanks Perderabo.. didn't realize there was such an easy way! Try this, scott:

if [ "$1" ]; then
  num=$1
  while [ $num -gt 0 ]; do
    echo $num
    ((num=num-1))
  done
else
  echo You did it wrong
fi

It looks like your only mistake was ((num=$1-1)) because it causes an endless loop.

Thank you both so very much!! Works like it's supposed to and how I imagined it would!:slight_smile:

I have one more question about the following lines of code:

#!/bin/ksh

if [ "$1" ]; then
num=$1
while [ $num -gt 0 ]; do
echo $num
((num=num-1))
done
elif [ "$1" ]; then
num=$1
while [ $num -le 0 ]; do
echo Command line argument must be a positive number and not zero
done
else
echo You must enter one number on the command line
fi

I don't receive any error messages when I run this, but when I enter a negative number on the command line, nothing happens. Any suggestions?

If you are checking for positive numbers there are better ways to do it. But you could just change your if statement to:

if [ "$1" -gt 0 ]; then
just like you have in the while loop

Then make your echo statement read must be a postive number, and drop the elif.

what the script is supposed to do is that I want it to accept an integer and do the following:

  1. If it's positive and greater than zero, count down to one
  2. If no argument is entered at the command line, then to display a message.
  3. If a negative number is entered at the command line, I want a message to display saying to enter a positive number. I just can't get this step to work.

I'm just trying to learn loops and how to nest them inside of each other.

That will accomplish everything in that list.

if [ "$1 -gt 0 " ]; then
num=$1
while [ $num -gt 0 ]; do
echo $num
((num=num-1))
done
else
echo Please Enter a Positive Integer
fi

Try this out, scott: :slight_smile:

if [ "$1" ]; then
  num=$1
  if [ "$1 -gt 0" ]; then
    while [ $num -gt 0 ]; do
      echo $num
      ((num=num-1))
    done 
  else
    echo "Enter a positive number!"
  fi
else 
  echo "Enter a number!"
fi

This: if [ "$1 -gt 0" ]; then
is not going to do what you think it might do.

But also, why are there two errors messages? First we reject input because it's not an integer, then we reject input because it's not a positive integer. User's don't like it when the requirements seem to change like that. Error messages really need to go to stderr as a rule anyway. How about:

#! /usr/bin/ksh

if [[ $1 = ?(+)+([0-9]) ]] ; then
      ((num=$1))
      while ((num)) ; do
            echo $num
            ((num=num+1))
      done

else

      echo enter a positive integer  >&2
fi
exit 0

Now as much as I love structured programming, I would never code like that in real life. I think that an early exit is fine. The real goal of structured programming is easily readable code. I only want to nest one structure inside another when I must. So I would actually go with

#! /usr/bin/ksh

if [[ $1 != ?(+)+([0-9]) ]] ; then
        echo enter a positive number >&2
        exit 1
fi

((num=$1))
while ((num)) ; do
       echo $num
       ((num=num+1))
done

exit 0

And to answer the question before it's asked, ?(+)+([0-9]) is a ksh pattern for a positive integer. ?() optionally matches any of the patterns inside the parentheses, so ?(+) will optionally match a plus sign. +() matches one or more of the patterns inside the parentheses, so +([0-9]) matches one or more numbers.

Well of course I was going to code it just like that, but I thought the OP wanted to practice with nested loops. :wink: :stuck_out_tongue:

Thank you all, once again.

oombera, I understand your code the best because it's a little more simple for me to read and understand, but none of the error messages triggered when I tried it out.

Perderabo, Your code worked perfectly for me. I don't understand all the code as much, but it works and thank you for the explanation. I just wanted to try nesting loops and have it fire off different error messages for specific occurances, like not positive, no argument, etc.

I know code should be short and simple, but for me who is just beginning, the long way is more simple.

Thank you again!

Scott

Another thing on syntax....

On HP-UX:

((num=num-1))

is about a LOT faster than:

num=`expr $num - 1`

Try them both and use timex to show the difference.

l8r~