Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using getopts inside a Bash function

I'd like to use getopts inside a function that I have defined in my .bash_profile. The idea is I'd like to pass in some flags to this function to alter its behavior.

Here's the code:

function t() {     echo $*     getopts "a:" OPTION     echo $OPTION     echo $OPTARG } 

When I invoke it like this:

t -a bc 

I get this output:

-a bc ?   

What's wrong? I'd like to get the value bc without manually shifting and parsing. How do I use getopts correctly inside a function?

EDIT: corrected my code snippet to try $OPTARG, to no avail

EDIT #2: OK turns out the code is fine, my shell was somehow messed up. Opening a new window solved it. The arg value was indeed in $OPTARG.

like image 556
Magnus Avatar asked May 20 '13 17:05

Magnus


People also ask

What is getopts in shell script?

Description. The getopts command is a Korn/POSIX Shell built-in command that retrieves options and option-arguments from a list of parameters. An option begins with a + (plus sign) or a - (minus sign) followed by a character. An option that does not begin with either a + or a - ends the OptionString.

Should I use getopt or getopts?

The main differences between getopts and getopt are as follows: getopt does not handle empty flag arguments well; getopts does. getopts is included in the Bourne shell and Bash; getopt needs to be installed separately. getopt allows for the parsing of long options ( --help instead of -h ); getopts does not.

How do you pass an argument in Bash?

To pass any number of arguments to the bash function simply put them right after the function's name, separated by a space. It is a good practice to double-quote the arguments to avoid the misparsing of an argument with spaces in it. The passed parameters are $1 , $2 , $3 …

What is $@ in Bash?

bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.


Video Answer


1 Answers

As @Ansgar points out, the argument to your option is stored in ${OPTARG}, but this is not the only thing to watch out for when using getopts inside a function. You also need to make sure that ${OPTIND} is local to the function by either unsetting it or declaring it local, otherwise you will encounter unexpected behaviour when invoking the function multiple times.

t.sh:

#!/bin/bash  foo() {     foo_usage() { echo "foo: [-a <arg>]" 1>&2; exit; }      local OPTIND o a     while getopts ":a:" o; do         case "${o}" in             a)                 a="${OPTARG}"                 ;;             *)                 foo_usage                 ;;         esac     done     shift $((OPTIND-1))      echo "a: [${a}], non-option arguments: $*" }  foo foo -a bc bar quux foo -x 

Example run:

$ ./t.sh a: [], non-option arguments: a: [bc], non-option arguments: bar quux foo: [-a <arg>] 

If you comment out # local OPTIND, this is what you get instead:

$ ./t.sh a: [], non-option arguments: a: [bc], non-option arguments: bar quux a: [bc], non-option arguments: 

Other than that, its usage is the same as when used outside of a function.

like image 181
Adrian Frühwirth Avatar answered Oct 10 '22 09:10

Adrian Frühwirth