Well, a very small note on getopts

    And so, we want to parse the command line parameters in our script, and we want to take into account
    • Options without arguments
    • Options with Arguments
    • Check for missing argument
    • Check unknown options
    • Check for missing parameters
    • Make this part of the script as a function

    And here you have the most laborious way that I could come to

    #!/bin/bash
    function check_arg(){
    	if [[ $2 == -* ]]; then 
    		echo "Option $1 requires an argument" >&2
    		exit 1
    	fi
    }
    function parse_param()
    {
    	if [ -z "$1" ];then
    		echo "Empty list of options" >&2
    		exit 1
    	fi
    	while getopts ":np:" opt; do
    		case $opt in
    		p)
    			check_arg "-p" "$OPTARG"
    			echo "-p(param) was triggered, Parameter: '$OPTARG'"
    		;;
    		n)
    			echo "-n(no param) was triggered"
    		;;
    		\?)
    			echo "Invalid option: -$OPTARG" >&2
    			exit 1
    		;;
    		:)
    			echo "Option -$OPTARG requires an argument (getopts)" >&2
    			exit 1
    		;;
    		esac
    	done
    }
    parse_param "$@"
    

    And here is an example of its use
    [bash]$ ./test.sh
    Empty list of option
    [bash]$ ./test.sh -m
    Invalid option: -m
    [bash]$ ./test.sh -n
    -n(no param) was triggered
    [bash]$ ./test.sh -n -p
    -n(no param) was triggered
    Option -p requires an argument (getopts)
    [bash]$ ./test.sh -p -n
    Option -p requires an argument
    [bash]$ ./test.sh -p"1 2 3"
    -p(param) was triggered, Parameter: '1 2 3'
    

    Why did I write all this? Indeed, it’s probably all painted on the Internet for a long time. I'll explain now. As I walked towards this simple implementation, I got on the rake many times using getopts in the context in which I needed. Therefore, I would like to describe below the rake that I got up along the way, and which brought me, I hope that the right way to use getopts.
    Getopts in function

    Errors can lie in the way you pass arguments to this function, for example, two wrong ways
    parse_param $1 $2 $3
    parse_param "$1" "$2" "$3" 
    

    In the first case, if you passed an argument to the script itself like this
    [bash]$ ./test.sh -p"1 2 3"
    

    Then they get to the parse_param function as parse_param –p 1 2 3, which, believe me, is not what you expected.
    Scrambling arguments helps, but I'm causing another problem. Now this part will stop working
    		:)
    			echo "Option -$OPTARG requires an argument (getopts)" >&2
    			exit 1
    		;;
    

    In place of this, $ OPTARG will be an empty string, which is quite valid from the point of view of getopts.
    So do it simply and correctly like this
    parse_param "$@"

    Options with arguments and argument checking

    To enable initial protection against the absence of an argument, each such option must be completed with a “:” sign and add the appropriate handler
    		:)
    			echo "Option -$OPTARG requires an argument (getopts)" >&2
    			exit 1
    		;;
    

    Why is this stray here?
    function check_arg(){
    	if [[ $2 == -* ]]; then 
    		echo "Option $1 requires an argument" >&2
    		exit 1
    	fi
    }
    

    Try to remove the call to this function here.
    check_arg "-p" "$OPTARG"
    

    And make such a call
    [bash]$ ./test.sh -p -n
    

    And you get that “-n” becomes the –p option argument. Is that what you expected? But not me.
    Invalid arguments

    In order for this piece of code to do what you want
    		\?)
    			echo "Invalid option: -$OPTARG" >&2
    			exit 1
    		;;
    

    The list of getopts parameters should begin with ":" (getopts " : np:")
    I hope it didn’t get too emotional, and this will save someone time for more interesting activities.

    Also popular now: