Sign in with
Sign up | Sign in
Your question

UNIX beginner

Last response: in Applications
Share
April 29, 2010 6:27:29 PM

Hi, I am taking my first UNIX class in school and I am very confused on my 3rd script I have to write. I am hoping some of you can help me. Well what I have to do is write a script that when I execute it is takes the largest number. For example say I write a script called largest, I then execute it ./largest 50 100 90 5, it should tell me the largest number in the set. So it should say "The largest number is 100." You should be able to enter up to 9 numbers. Okay well this is what I have and I don't know why it isn't working.

count=$#
args=("$@")
max=$1

while [ $count -gt 0 ]
do
num=${args[count]}
if test num -gt max
then
let max=num
let count=count-1
fi

done
echo "The largest number is $max"
echo "Done"
exit 0


what I am trying to do is set the first number entered into max then go through the array each time assigning the value to num, then I want to test the value in num to see if its greater then max and if it is then that value will take over the max value. For example say I enter ./largest 50 10 6 90. max will be set at 50 then num would be set to whatever is in array 4 which would be 90. Then is will see if num(90) is greater then max(50) and since it is max will become 90. then it will go down the list so num will become the next array which is 6 and do the same test and since 6 isnt greater than 50 max will remain as 50. So it will do this for all the numbers and the largest number will be in max. Then "echo "The largest number is $max"" will print out the largest number. Seems like it should work but it keeps saying "./sum line 8: test: num: integer expression expected" no clue what to do. Please help.vi

More about : unix beginner

a b L Programming
April 29, 2010 7:24:14 PM

You've got the basic idea, but you've made a few trivial mistakes.

1. You've decremented count inside the test. Initially $max and $num are going to be the value of the last member of the array. The test is always going to fail, count will never get decremented, so you have an infinite loop.

2. You've got a number of variable references where $ is missing. Remember, to extract the value of the variable you need to preceed it with $. For example, first time you access the args array you have args[count]; this should be args[$count].

3. You're treating the array as if it were args[1], args[2], .... But arrays start from 0, so it should be args[0], args[1], .... There's a couple of ways you could correct this - replacing args[$count] with args[$count - 1] is probably the easiest.

1. was just a moments lapse, 2. & 3. are very common mistakes when beginning shell scripting. I'm not going to reproduce a correct program here as I'm sure that you are bright enough to correct it, and you'll learn more that way.
m
0
l
April 29, 2010 7:49:04 PM

Thanks a lot, I will trying to correct this, I did try putting $ in front of the variables but still didn't work so I just ignored it but never put the count-1 outside the loop. I am great in my C++ classes but UNIX owns me and my teacher is a retard, showed her my script and she never pointed out any of the things you said.
m
0
l
Related resources
a b L Programming
April 29, 2010 7:56:13 PM

I must confess that I didn't immediately spot any of the errors, although if I'd thought about it I would have, execpt the misplacement of the count = $count - 1 statement.

So I did what you should always do - inserted a few judicious "echo" statements to see what was happening to the variables. It was then fairly obvious what was wrong.
m
0
l
a b L Programming
April 30, 2010 1:30:16 PM

I'd like to add a few comments over what others have said.

First, you can use the [ code ] [ / code ] brackets in the forum to keep indentation (example lower).

Second, if using bash, you can use some sort of "foreach" loop where the field seperator in stored in the IFS variable (default is space I think). Example:
  1. #!/bin/bash
  2. for ARG in "$@"
  3. do
  4. echo "ARG: $ARG"
  5. done


Third, the brackets ([ ]) can be used instead of "test", you used it in your while statement, but not in your if statement, I don't know if you did it on purpose.
m
0
l
April 30, 2010 4:44:30 PM

Ok redid the code, added the $ to all variables, for the let count = count-1 should it be let $count=$count-1 because when I did that it gave an error? it works when the largest number is entered first but when its not it gives me an error:

./sum 10 30 12

./sum: line 9: let: 10=12: attempted assignment to non-variable (error token is "=12")

./sum: line 9: let: 10=30: attempted assignment to non-variable (error token is "=30")

The largest number is 10
Done


Do I have to declare num somewhere. that is what the error seems to be saying? I am so confused with UNIX way of declaring variables. Seems like You can put them anywhere and they are declared unlike C++.


  1. count=$#
  2. args=("$@")
  3. max=$1
  4. while [ $count -gt 0 ]
  5. do
  6. num=${args[$count - 1]}
  7. if [ $num -gt $max ]
  8. then
  9. let $max=$num
  10. fi
  11. let count=count-1
  12.  
  13.  
  14. done
  15. echo "The largest number is $max"
  16. echo "Done"
  17. exit 0


I was also confused on why count=count-1 had to be outside the loop but now I see that this is a nested loop and the count-1 is still in the while loop where it should of been.
m
0
l
a b L Programming
April 30, 2010 5:22:17 PM

With "let", I think you don't need the $ sign, that is why it's giving you an error.

As for not needing explicit declaration, you are right, in most Linux/Unix shell (BASH/KSH/...) you don't declare variable, you just start using them. This can be very confusing and error-prone so you need to be careful.

Instead of using "let", in BASH you can also use $(( )) like this: count=$(( count - 1 )). If you want more information, you can check here.
m
0
l
a b L Programming
April 30, 2010 5:44:29 PM

No $ on the left-hand side (because you're not extracting the value of the variable). So
  1. let max = $num
  2. let count = $count -1
etc. But you need it in the comparisons, becasue there you are extracting the value of each variable:
  1. if [$num -gt $max]
etc.
m
0
l
April 30, 2010 11:51:36 PM

WooHoo it works thanks a lot guys. God I like c++ so much better. UNIX is so confusing. Ok so when using let the variable on the left never uses $ but the one on the right does.
m
0
l
a b L Programming
May 1, 2010 6:48:09 AM

It seems illogical, but it's not really. When you are working with variables you are concerned with two things.

A container (the variable)
Something in the container (the value of the variable)

In UNIX shell scripts you refer to a variable by a name, say foo, and it's contents as $foo. So the "$" extracts the value from the variable. So in an assigment you want to take the contents of one container and store it in another. Hence:
  1. let variable1 = $variable2

Most programming lanuguages hide this from you, although C and C++ let you see the gory details in the form of pointers (which beginners can find equally confusing).
m
0
l
a b L Programming
May 1, 2010 5:18:10 PM

BTW, I'd like to point-out that BASH is not a programming language, it's a scripting language (a very powerful one, but still). To compare BASH to C++ is as fair as comparing DOS batch syntax to C++. BASH script are executed by the same shell you use when in CLI mode.
m
0
l
!