Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
First, are you using Bash's builtin [, or are you using an external implementation of [? Here's how to find out; if it is Bash's [ then it doesn't understand the --help option.
Code:
tmp$ [ --help
bash: [: missing `]'
Note that it was Bash which responded with an error message.
Now in your script, here's the problem line:
Code:
while [ !($numchoice -ge 1) && !($numchoice -le 4) ]
# ^ command list separator
The problem is that && is interpreted by Bash as a command list separator. That's why the closing ] isn't recognized. Everything after && is treated as a separate stanza of the command list.
Numeric tests should properly be done in bash using ((..)), and string tests in [[..]]. The only time you need to use the old single bracket [ is when you're writing posix-compliant scripts for systems without bash.
select is good for simple menus, but it's often necessary to roll your own for more complex stuff. Most experienced scripters tend to emulate select and put the menu in a never-ending while true loop, using an if or case statement inside to evaluate the choice made, and break commands to exit the loop when desired.
Untested, but to demonstrate the principle...
Code:
#!/bin/bash
menu='
1. healthchk
2. bpipwd
3. cust_usage_check
4. other scripts automatic
enter choice [1 | 2 | 3 | 4 ]: '
while true; do
echo -n "$menu"
read numchoice
if (( numchoice >= 1 && numchoice <= 4 )); then
echo -n "you entered incorrect, try again: "
else
echo "you chose $numchoice. goodbye!"
break
fi
done
I just tried to answer OP's qyestion as directly as possible. My previous reply doesn't seem very clear. Here is a much better explanation of the problem I see in OP's code:
David the H., I think you forgot the $ signs in your if statement.
This worked for me:
Code:
$ cat tmp.bash
#!/bin/bash
while [ $# -gt 0 ]
do
numchoice=$1
shift
if (( $numchoice >= 1 )) && (($numchoice <= 4 ))
then
echo Yes
else
echo No
done
$ ./tmp.bash 0 1 2 3 4 5 6 7 8 9 10
No
Yes
Yes
Yes
Yes
No
No
No
No
No
No
Last edited by PTrenholme; 11-04-2011 at 04:41 PM.
Reason: Cat "assisted" prior post . . .
David the H., I think you forgot the $ signs in your if statement.
Actually, he did not. Variables do not have to be preceded by $ inside ((...)). At least not in bash v4.1.5. I know, it is inconsistent.
There is more confusion about ((...)). Consider the following:
Code:
num=3
if (( num = 5 )); then echo true;else echo false;fi
true
echo $num
5
As you can see, the '=' does an assignment to num. The 'classic' [[ ... ]] treats it as comparison operator:
Code:
num=3
if [[ $num = 5 ]]; then echo true;else echo false;fi
false
echo $num
3
If you want to compare the variable for equality inside (( ... )) you have to use '=='
Code:
num=3
if (( num == 5 )); then echo true;else echo false;fi
true
echo $num
3
That's right. In any arithmetic environment field, the only recognized strings are digits and mathematical operators. So when the shell sees an alphabetical string, it assumes it's a variable and automatically expands it before evaluation. It saves a bit of typing and clutter, at the least.
As far as I know, this is true of all bourne-based shells. It's likely even a posix specification, although I haven't confirmed that.
By the way, not only is "=" a comparison operator inside the [ and [[ bracket tests, it's a string comparison; the two sides will be evaluated according to their alphanumeric/ascii order values. For an arithmetic comparison, you must use "-eq" and similar. That's one reason the ((..)) test is recommended, it makes it clear at a glance that it's an arithmetic operation, and lets you use the more natural math operators you're used to (with the exception of the "=/==" difference explained above).
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.