LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This 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


Reply
  Search this Thread
Old 11-03-2011, 10:06 PM   #1
greenpool
Member
 
Registered: Sep 2010
Posts: 41

Rep: Reputation: 0
menu with while loop


I'm trying create a menu with a while loop in the following manner

Code:
#!/bin/bash


echo -n "

1. healthchk
2. bpipwd
3. cust_usage_check
4. other scripts automatic

enter choice [1 | 2 | 3 | 4 ]: "
read numchoice



while [ !($numchoice -ge 1) && !($numchoice -le 4) ]
do
echo -n "you entered incorrect, try again: "
read numchoice
done
error i'm getting is:

[: missing `]'


I suspect its something to do with my syntax. can someone please tell me what i'm doing wrong, thanks!
 
Old 11-03-2011, 11:58 PM   #2
mladoux
LQ Newbie
 
Registered: Aug 2011
Posts: 4

Rep: Reputation: Disabled
while loops don't work quite like that. This guide will show you where you've gone wrong:

http://tldp.org/LDP/abs/html/loops1.html
 
Old 11-04-2011, 12:19 AM   #3
smilesavvy
LQ Newbie
 
Registered: Nov 2011
Posts: 5

Rep: Reputation: Disabled
Don't use While loop for menu. use " select ".
Code:
#!/bin/bash
PS3="Choose the correct option:  "
select i in healthchk bpipwd cust_usage_check other_scripts_automatic
do
  case $i in
  healthchk) echo "you selected option 1";;
  bpipwd) echo "you selected option2";;
  cust_usage_check) echo "you selected option 3";;
  other_scripts_automatic) echo " you selected option 4";;
  *) echo " you have entered wrong option, please choose the correct option from the listed menu."
     sleep 5
     exit;;
  esac
done

-- Ramesh Jonathan Godishela
 
1 members found this post helpful.
Old 11-04-2011, 12:43 AM   #4
devUnix
Member
 
Registered: Oct 2010
Location: Bengaluru, India
Distribution: RHEL 5.1 on My PC, & SunOS / Sun Solaris, RHEL, SuSe, Debian, FreeBSD and other Linux flavors @ Work
Posts: 584

Rep: Reputation: 59
Here is what I use:


Code:
#!/bin/bash
numchoice=1
while [ $numchoice != 0 ]; do
 echo -n "
 1. healthchk
 2. bpipwd
 3. cust_usage_check
 4. other scripts automatic
 0. Exit

 enter choice [1 | 2 | 3 | 4 ]: "
 read numchoice
 case $numchoice in
        "1" ) ./healthchk.sh ;;
        "2" ) ./bpipwd.sh ;;
        "3" ) ./cust.sh ;;
        "4" ) ./other.sh ;;
        "0" ) break ;;
        * ) echo -n "You entered an incorrect option. Please try again." ;;
 esac
done

Here is a sample run of the above script:

Code:
$ /bin/bash h.sh

 1. healthchk
 2. bpipwd
 3. cust_usage_check
 4. other scripts automatic
 0. Exit

 enter choice [1 | 2 | 3 | 4 ]: 1
h.sh: line 14: ./healthchk.sh: No such file or directory

 1. healthchk
 2. bpipwd
 3. cust_usage_check
 4. other scripts automatic
 0. Exit

 enter choice [1 | 2 | 3 | 4 ]: 5
You entered an incorrect option. Please try again.
 1. healthchk
 2. bpipwd
 3. cust_usage_check
 4. other scripts automatic
 0. Exit

 enter choice [1 | 2 | 3 | 4 ]: 0

You can remove these double quotes:

Code:
        "1" ) ./healthchk.sh ;;
        "2" ) ./bpipwd.sh ;;
        "3" ) ./cust.sh ;;
        "4" ) ./other.sh ;;
        "0" ) break ;;
but do not quote the star (*).

You see:

Code:
h.sh: line 14: ./healthchk.sh: No such file or directory
because I did not write the healthchk.sh script for you. You do that!
 
1 members found this post helpful.
Old 11-04-2011, 12:55 AM   #5
Telengard
Member
 
Registered: Apr 2007
Location: USA
Distribution: Kubuntu 8.04
Posts: 579
Blog Entries: 8

Rep: Reputation: 148Reputation: 148
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.
 
Old 11-04-2011, 04:32 AM   #6
Fantastic
LQ Newbie
 
Registered: Nov 2010
Distribution: Archlinux
Posts: 18

Rep: Reputation: 0
change line with while definition to

while [ $numchoice -lt 1 -a $numchoice -gt 4 ]
 
Old 11-04-2011, 07:37 AM   #7
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960
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.

http://mywiki.wooledge.org/ArithmeticExpression
http://mywiki.wooledge.org/BashFAQ/031

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
 
1 members found this post helpful.
Old 11-04-2011, 01:31 PM   #8
Telengard
Member
 
Registered: Apr 2007
Location: USA
Distribution: Kubuntu 8.04
Posts: 579
Blog Entries: 8

Rep: Reputation: 148Reputation: 148
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:

BashPitfalls - Greg's Wiki:6. [ "$foo" = bar && "$bar" = foo ]

All the replies I see here now bring up other important points too, and IMHO OP should heed them.

HTH
 
Old 11-04-2011, 04:33 PM   #9
PTrenholme
Senior Member
 
Registered: Dec 2004
Location: Olympia, WA, USA
Distribution: Fedora, (K)Ubuntu
Posts: 4,186

Rep: Reputation: 346Reputation: 346Reputation: 346Reputation: 346
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 . . .
 
Old 11-04-2011, 06:56 PM   #10
crts
Senior Member
 
Registered: Jan 2010
Posts: 1,614

Rep: Reputation: 450Reputation: 450Reputation: 450Reputation: 450Reputation: 450
Quote:
Originally Posted by PTrenholme View 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
@OP: Sorry for taking this a bit off topic.
 
Old 11-05-2011, 12:14 PM   #11
PTrenholme
Senior Member
 
Registered: Dec 2004
Location: Olympia, WA, USA
Distribution: Fedora, (K)Ubuntu
Posts: 4,186

Rep: Reputation: 346Reputation: 346Reputation: 346Reputation: 346
Yes, you're correct.

In fact, both (( numchoice >= 1 )) && (( numchoice <= 4 )) and (( numchoice >= 1 && numchoice <= 4 )) work as the object of the if with bash 4.2.10.

I plead being set in my ways after 70 odd years . . .
 
Old 11-05-2011, 01:23 PM   #12
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960Reputation: 1960
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).
 
1 members found this post helpful.
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
how to loop over text file lines within bash script for loop? johnpaulodonnell Linux - Newbie 9 07-28-2015 03:49 PM
[SOLVED] Bash - While Loop reading from two lists simultaneously - nested while loop wolverene13 Programming 11 10-01-2011 05:00 PM
for loop or while loop to read the fields of a file.. visitnag Linux - Newbie 10 09-02-2010 08:47 PM
Script Errors (loop, menu, etc, not found) dolvmin Linux - Software 7 08-14-2003 12:50 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 01:04 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration