View Full Version : shell script- use arithmetic with case
voltronguy
October 18th, 2006, 03:36 PM
Hi All,
I'm learning how to write very basic shell scripts. I understand the architecture of using case. What I can't figure out is how use arithmetic arguments like you can use with if/then.
Here is what I am trying to do:
echo -n "How old are you? "
read age
case $age in
26) echo "Same age" ; sleep 3s ;;
[<26]) echo "Younger than me" ; sleep 3s ;;
[>26]) echo "Older than me" ; sleep 3s ;;
*) echo "no" ; sleep 3s ;;
esac
clear
Notice the bolded arguments. How can I do something like that? Or am I stuck with a straight equals or doesn't equal value?
Thanks for any help.
Arndt
October 18th, 2006, 03:54 PM
Hi All,
I'm learning how to write very basic shell scripts. I understand the architecture of using case. What I can't figure out is how use arithmetic arguments like you can use with if/then.
Here is what I am trying to do:
echo -n "How old are you? "
read age
case $age in
26) echo "Same age" ; sleep 3s ;;
[<26]) echo "Younger than me" ; sleep 3s ;;
[>26]) echo "Older than me" ; sleep 3s ;;
*) echo "no" ; sleep 3s ;;
esac
clear
Notice the bolded arguments. How can I do something like that? Or am I stuck with a straight equals or doesn't equal value?
Thanks for any help.
With 'case', you can use matching expressions using '?' and '*', as in filename expansion, but that doesn't help with your arithmetic.
The command 'expr' can be used to compare values:
age=23
$ expr $age '<' 21
0
$ expr $age '<' 26
1
And so can the command 'test', which has a special syntax in the shell:
if [ $age '<' 26 ]; then
echo less
elif [ $age '>' 26 ]; then
echo more
else
echo equal
fi
ghostdog74
October 18th, 2006, 03:55 PM
Hi All,
I'm learning how to write very basic shell scripts. I understand the architecture of using case. What I can't figure out is how use arithmetic arguments like you can use with if/then.
Here is what I am trying to do:
echo -n "How old are you? "
read age
case $age in
26) echo "Same age" ; sleep 3s ;;
[<26]) echo "Younger than me" ; sleep 3s ;;
[>26]) echo "Older than me" ; sleep 3s ;;
*) echo "no" ; sleep 3s ;;
esac
clear
Notice the bolded arguments. How can I do something like that? Or am I stuck with a straight equals or doesn't equal value?
Thanks for any help.
if you use if/then construct, you can check greater than using -gt or less than -lt ...
hillbilly
October 18th, 2006, 04:02 PM
I dont thnk you can set a condition in the patterns of the case statement. You can only use wild cards. (e.g. "*6" and so on.)
If you need to set something like less than or greater than, then you are better off using if-elif.
Or if you are still particular about using case, you could first capture the return value of the expression $age==26 and then use that return value as an argument to case. But then thats a round about way ;)
voltronguy
October 18th, 2006, 04:09 PM
Thank you all for the replies. The problem with the if/then was that I couldn't get it to handle non-numerical input.
echo -n "How old are you? "
read age
if [ "$age" = 26 ];
then echo "We are the same age!" ; sleep 3s
elif
(Line 17) [ "$age" -lt 26 ];
then echo "You are younger than me." ; sleep 3s
(Line 19) elif [ "$age" -gt 26 ];
then echo "You are older than me." ; sleep 3s
else echo "You aren't human!" ; sleep 3s
fi
The script works fine until you give it a letter as an input. While it does give the correct output (echo "You aren't human"), it tosses out errors for the =,<,>26 tests where it was expecting a number.
./age: line 17: [: x: integer expression expected
./age: line 19: [: x: integer expression expected
You aren't human!
That's why I was hoping to use case, since the * could handle non-numerical input.
hillbilly
October 18th, 2006, 04:16 PM
When you do numeric comparisions, you should use -eq for equal, -le for less than, -ge for greater than and so on. I dont recollect all the codes for comparision operators, but you could check out "man test" and you should be able to find it.
==, <, > all work only for string comparisions.
NOTE: ghostdog74 had mentioned this in his post.
PLEASE disregard this post :( , was dreaming when i wrote this I guess !!
Arndt
October 18th, 2006, 04:21 PM
The script works fine until you give it a letter as an input. While it does give the correct output (echo "You aren't human"), it tosses out errors for the =,<,>26 tests where it was expecting a number.
./age: line 17: [: x: integer expression expected
./age: line 19: [: x: integer expression expected
You aren't human!
That's why I was hoping to use case, since the * could handle non-numerical input.
Use 'expr match' to first reject non-numbers:
$ expr match twenty '[0-9]*$'
0
$ expr match 26 '[0-9]*$'
2
voltronguy
October 18th, 2006, 07:45 PM
Thanks for the suggestion. I couldn't follow the syntax you were using, but I poked around till I got something to work. First I have the script check for how many letters are in the age variable
echo -n "What is your age? "
read age
lettercheck=`expr $age : [[:alpha:]]*$`
Then if there are any letters I have the routine start over
if [ $lettercheck -gt 0 ]; then
clear ; echo "Please enter a number only" ;
Now I just need to get a similar check for a blank entry and the script will be in good shape.
morgan_greywolf
October 18th, 2006, 11:01 PM
You can also do this if you want something more case like. This combines the arithmetic expression evaluation capabilities of bash/ksh with the if/elif/fi:
#!/bin/bash
echo -n "Enter your age: "
read age
if (( age <= 0 )); then
echo "You are not human!"
elif (( age > 26 )); then
echo "You are older than me!"
elif (( age < 26 )); then
echo "You are younger than me!"
elif (( age == 26 )); then
echo "Hey! We're the same age!"
fi
Arndt
October 19th, 2006, 08:20 AM
Thanks for the suggestion. I couldn't follow the syntax you were using, but I poked around till I got something to work. First I have the script check for how many letters are in the age variable
echo -n "What is your age? "
read age
lettercheck=`expr $age : [[:alpha:]]*$`
Then if there are any letters I have the routine start over
if [ $lettercheck -gt 0 ]; then
clear ; echo "Please enter a number only" ;
I think your 'expr' call doesn't do what you want:
$ expr abc : [[:alpha:]]*$
3
$ expr abc6 : [[:alpha:]]*$
0
$ expr 66 : [[:alpha:]]*$
0
hillbilly
October 19th, 2006, 03:18 PM
.
.
.
echo -n "What is your age? "
read age
lettercheck=`expr $age : [[:alpha:]]*$`
Then if there are any letters I have the routine start over
if [ $lettercheck -gt 0 ]; then
clear ; echo "Please enter a number only" ;
Now I just need to get a similar check for a blank entry and the script will be in good shape.
Just a suggestion:
echo $age | grep [a-zA-Z]
echo $? ## Return code of the above command
would tell whether there are alphabets in your variable.
Powered by vBulletin® Version 4.2.2 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.