ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
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.
I mean ./script.sh -i eth0 192.168.1.1 255.255.255.0 1500 and ./script.sh 192.168.1.1 -i eth0 255.255.255.0 1500 and ./script.sh 192.168.1.1 255.255.255.0 1500 -i eth0 etc should all give the same output:
You are, of course, free to code whatever you like but a) the toolsets are written according to convention and b) users are programmed (!) to convention.
Last edited by catkin; 11-27-2009 at 12:42 AM.
Reason: punctuation
AFAIK getopts does not support arguments presented before the last option. This implements a long-standing convention, in use for more than 40 years.
You mean getopts doesn't support any not-getopts arguments placed before '-i eth0'? However, is there a possibility to stop getopts looking for options? I know this a silly example, but lets say:
./script.sh -i eth0 192.168.1.1 255.255.255.0 -1500
How to achieve that getopts doesn't take '-1500' as an option? In other words getopts should stop it's work after './script.sh -i eth0'
You mean getopts doesn't support any not-getopts arguments placed before '-i eth0'? However, is there a possibility to stop getopts looking for options? I know this a silly example, but lets say:
./script.sh -i eth0 192.168.1.1 255.255.255.0 -1500
How to achieve that getopts doesn't take '-1500' as an option? In other words getopts should stop it's work after './script.sh -i eth0'
getopts keeps processing options (and any associated option arguments) according to optstring until it encounters something which is not described by optstring.
In your example, assuming opstring is "i:" (note: no leading ":"), getopts would stop processing on finding 192.168.1.1. The usual idiom after getopts completes is to run shift $(( $OPTIND-1 )) leaving the command line words from 192.168.1.1 onward in $1, $2, $3 ...
Another convention, where non-option arguments may begin with "-" is to allow "-" as a special option to indicate the end of options (I have not ever needed to implement this). In the example you give it is not necessary because 192.168.1.1 terminates the options but it would be necessary, for example, if the command line were ./script.sh -i eth0 -1500 192.168.1.1 255.255.255.0 which would otherwise result in an invalid option "5".
Where '-eth0' is a value for option '-i'. Is it possible at all?
I just tried it and it worked OK using this generic getopts script (intended as a proforma for use in a function -- hence the indentation and comments with no following code)
Code:
#!/bin/bash
# Set defaults that may be overriden by command line parsing
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Parse command line
# ~~~~~~~~~~~~~~~~~~
emsg=''
while getopts dhVo: opt 2>/dev/null
do
case $opt in
d )
debug='YES'
;;
h )
usage -v
\exit 0
;;
V )
echo "$prgnam version $prg_ver"
\exit 0
;;
o )
o_optarg="$OPTARG"
;;
* )
emsg="${lf}Invalid option '$opt'"
esac
done
# Test for extra arguments
# ~~~~~~~~~~~~~~~~~~~~~~~~
shift $(( $OPTIND-1 ))
if [[ $* != '' ]]; then
emsg="${lf}Invalid extra argument(s) '$*'"
fi
# Test for mandatory options not set
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if [[ ${o_optarg:-} = '' ]]; then
emsg="${lf}Mandatory option -o not given"
fi
# Report any errors
# ~~~~~~~~~~~~~~~~~
if [[ $emsg != '' ]]; then
echo "$emsg" >&2
usage
\exit 1
fi
echo "DEBUG: o_optarg is '$o_optarg'"
Here's the call and output
Code:
c:~/d/bin/try$ ./getopts.sh -o -eth0
DEBUG: o_optarg is '-eth0'
That's not possible with getopts, AFAIK. getopts reads the parameters sequentially expecting to find only flags that start with "-" and the optional arguments that follow them. Any other entries that don't follow this pattern would confuse the $OPTARG and $OPTIND variables.
The way it works now also makes it easily possible to have arguments that start with "-", since otherwise they'd be seen as unrecognized options.
Just about all other programs out there follow this basic pattern as well.
I suppose it'd be possible to manually process the line and extract the address before applying getopts, but that would probably be much more trouble than its worth. I suggest either giving the ip number its own flag, or simply leaving it as-is.
That's not possible with getopts, AFAIK. getopts reads the parameters sequentially expecting to find only flags that start with "-" and the optional arguments that follow them. Any other entries that don't follow this pattern would confuse the $OPTARG and $OPTIND variables.
The way it works now also makes it easily possible to have arguments that start with "-", since otherwise they'd be seen as unrecognized options.
Just about all other programs out there follow this basic pattern as well.
I suppose it'd be possible to manually process the line and extract the address before applying getopts, but that would probably be much more trouble than its worth. I suggest either giving the ip number its own flag, or simply leaving it as-is.
ok, I see. Thanks for explanation! However, if somebody has an example with manual execution string processing which allows similar:
./getopts -r router_name 192.168.1.1 24 -i eth0
script executions, then I'll happily research those On the other hand, if it's very complicated and may bring along some errors, I'll leave it as it is.
It might be possible by incrementing OPTIND but you would be using an undocumented feature that might not be supported in a later version of bash; if you're OK with that and don't mind maybe having to fix your script (or someone else maybe having to fix your script) later.
A better approach might be to use -r router_name:192.168.1.1 24 on the command line. That way $OPTARG would be "router_name:192.168.1.1 24: and you could parse the components by
It might be possible by incrementing OPTIND but you would be using an undocumented feature that might not be supported in a later version of bash; if you're OK with that and don't mind maybe having to fix your script (or someone else maybe having to fix your script) later.
A better approach might be to use -r router_name:192.168.1.1 24 on the command line. That way $OPTARG would be "router_name:192.168.1.1 24: and you could parse the components by
Code:
name="${OPTARG%:*}"
ip="${OPTARG#*:}"
I see. However, it would be nice if the syntax of the execution line stays the same(and I don't mind repairing the script if it doesn't work in later versions of bash):
./getopts -r router_name 192.168.1.1 24 -i eth0
As I understand, OPTIND holds the index to the next argument to be processed. Default value for OPTIND should be 1. As I understand, every time that getopts finds a argument the value of the OPTIND is incremented by one? Now how does it help me if I increment OPTIND values manually?
As I understand, OPTIND holds the index to the next argument to be processed. Default value for OPTIND should be 1. As I understand, every time that getopts finds a argument the value of the OPTIND is incremented by one? Now how does it help me if I increment OPTIND values manually?
It is possible that getopts will use the changed OPTIND when choosing the next $1, $2, $3 ... $n to examine for one of the options specified by "r:i:". You could experiment.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.