LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > General
User Name
Password
General This forum is for non-technical general discussion which can include both Linux and non-Linux topics. Have fun!

Notices

Reply
 
Search this Thread
Old 04-26-2011, 09:15 AM   #1
nano2
Member
 
Registered: May 2007
Posts: 100

Rep: Reputation: 15
BASH script using getopt to parse optional arguments


Hi
i have the following scenario want to run the following script with manadory and optional argumnets

Manadory options are :

filename=""
port=""
optional arguments

type -t [A/B]
balances -b bal
prices -p

./test filename port -t A -b bal


my code i have that won't parse the options is
This is what i have
#!/bin/bash
filename=""
port=""

while getopts b:t opt
do
case $opt in
b) BAL="${OPTARG}"
if [ "$BAL" == "" ]
then
print_usage $0
else
echo "Balances is " $BAL
fi ;;

t) TYPE="$OPTARG";;
p) PRICES="$OPTARG";;
?) print_usage $0
exit 1;;
esac
done
echo "Balances: "$BAL
echo "Type: "$TYPE


Any ideas
~
 
Old 04-26-2011, 11:05 AM   #2
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,546
Blog Entries: 28

Rep: Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176
First idea is to use CODE tags to make your code more readable; you can most easily use them by changing to advanced mode posting and using the # button.

Copying your code into CODE tags:
Code:
#!/bin/bash
filename=""
port=""

while getopts b:t:p opt
 do
      case $opt in
          b) BAL="${OPTARG}"
             if [ "$BAL" == "" ]
             then
                print_usage $0
             else
                echo "Balances is " $BAL
             fi ;;

          t) TYPE="$OPTARG";;
          p) PRICES="$OPTARG";;
          ?) print_usage $0
             exit 1;;
      esac
done
echo "Balances:                "$BAL
echo "Type:                    "$TYPE
Second idea is to explain exactly what "won't parse the options" means, for example by copying and pasting the output into this thread.

Guessing what the problem is, getopts is traditional; it must have the options (and option arguments) before the arguments. Try
Code:
./test -t A -b bal filename port

Last edited by catkin; 04-26-2011 at 11:06 AM. Reason: removed full OP quote
 
Old 04-26-2011, 11:35 AM   #3
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
You also have to shift the parameters after processing the optional arguments so you can grab what's left.
Code:
while getopts b:t:p opt ; do
...
done

shift $(( OPTIND-1 ))

filename="$1"
port="$2"
This is a decent getopts tutorial:
http://wiki.bash-hackers.org/howto/getopts_tutorial

Edit: Thinking about it, It is possible instead to have the mandatory arguments first, if you really want it that way. Just reverse the above: set filename and port first, then shift the parameters by two so that the getopts loop can process the rest.

The thing you can't do is mix the two types arbitrarily. The getopts arguments pretty much have to come together as a group.

Not without some funky coding magic at least.

Last edited by David the H.; 04-26-2011 at 11:54 AM. Reason: as stated
 
Old 04-27-2011, 02:36 AM   #4
nano2
Member
 
Registered: May 2007
Posts: 100

Original Poster
Rep: Reputation: 15
Yes I have tried this inorder to place the manadory options first and then shift by 2 But I get the following error
-2: shift count out of range

Any ideas what i am doing wrong !

while getopts b:t opt ; do
...

done
filename="$1"
port="$2"

shift $(( OPTIND-2 ))
 
Old 04-27-2011, 08:11 AM   #5
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
1) As catkin asked above, please use [code][/code] tags around your code, to preserve formatting and to improve readability.

2) As I said, you have to reverse the process. Save the first two parameters to variables first, then shift 2 to remove them from the command list, then use getopts on the rest.
Code:
filename="$1"
port="$2"

shift 2

while getopts ...
Be aware that this means filename and port must always come first, and in that order, since they are processed first in the code and then their parameters are discarded.

Again, this just reverses the traditional pattern, where the getopts options are processed first, and discarded, so that whatever is left can be used in other ways.

Look at the link I gave you and carefully read how getopts works. Look up what shift does too if necessary (hint, there's a link to "handling positional parameters" on that page that explains it, along with other useful info related to this topic).

Or you could just give the "mandatory" arguments their own getopts flags too, then you wouldn't have to worry about the order they come in at all.
 
Old 04-27-2011, 03:17 PM   #6
nano2
Member
 
Registered: May 2007
Posts: 100

Original Poster
Rep: Reputation: 15
David ,
how could I achieve this inside the getopts would i need to pass in aoption for the filename etc
eg -f ?

" you could just give the "mandatory" arguments their own getopts flags too, then you wouldn't have to worry about the order they come in at all. "

Code:
while getopts b:t:p opt
 
Old 04-28-2011, 08:09 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: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
Yes, just give them their own flags.

What makes an option "mandatory" or "optional" is not whether it has a getopts flag, it's all in what tests you run when and after you process the parameter. All getopts does is provide an easy way to have a flag-style input.

So, just add a "f:" to flags list, and use that to set the filename variable inside the getopts loop. Then after finishing getopts, run a test on that variable to see if the file exists. If it doesn't, throw up an error.
Code:
while getopts b:t:f:P:p opt ; do

   ...
   -f) filename=$OPTARG ;;
   -P) port=$OPTARG ;;
   ...

done

if [[ -z $filename  ]] ; then

   echo "A filename must be supplied (with the "-f" flag)."
   exit 1

elif [[ ! -e $filename ]]; then

   echo "The filename provided does not exist."
   exit 1

elif [[ ! -r $filename ]]; then

   echo "The filename provided is not readable.  Check your permissions."
   exit 1
fi
...and so on..
 
  


Reply

Tags
argument, bash scripting, getopts, parameters


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 are arguments passed to a bash script? jiml8 Programming 1 04-09-2009 05:28 PM
bash script - parsing optional parameters yitzle Programming 5 02-17-2008 11:16 AM
bash script arguments R3N3G4D3 Programming 5 11-01-2007 10:16 AM
bash script - variable arguments indikabandara19 Linux - Newbie 4 05-21-2007 10:40 PM
Optional arguments in Python forsaken_pariah Programming 1 03-10-2007 09:48 AM


All times are GMT -5. The time now is 09:01 PM.

Main Menu
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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration