Reputation: 668
I got a weird error when using the following getopt
when passing the -
character. Here is the example of the code and the output:
#!/bin/bash
function _echo()
{
msg="$1"
# A sample getopt option with only t as short parameter
# I put -q to silent error and use output based on getopt return status
options=$(getopt -q -o t -- "$@")
retval=$?
if [ ${retval} -ne 0 ]; then
echo "${msg} <--[this has error]"
else
echo "${msg} <--[this is ok]"
fi
echo ""
eval set -- "${options}"
}
# Calling function _echo() without passing any option (sample):
_echo "--" # OK
_echo "Hello" # OK
_echo "Hello--" # OK
_echo "-" # OK
_echo "---------------" # Error
_echo "---" # Error
_echo "--Hello" #Error
_echo "-Hello" #Error
Output:
-- <--[this is ok]
Hello <--[this is ok]
Hello-- <--[this is ok]
- <--[this is ok]
--------------- <--[this has error]
--- <--[this has error]
--Hello <--[this has error]
-Hello <--[this has error]
You can see that some of the above statements passed to _echo
function have errors even the strings are quoted ? How do you overcome this problem if you want to pass the long dash character (-------
) inside the _echo function ?
Thanks.
Upvotes: 1
Views: 1103
Reputation: 311526
Quoting doesn't matter...there's no difference between calling _echo --Hello
vs calling _echo "--Hello"
. In both cases, the _echo
function receives a single parameter, --Hello
. Since you only accept the parameter -t
, anything else that looks like a parameter is going to cause an error.
The correct way of handling this is described in the getopt
man page:
Each parameter after a '--' parameter is always interpreted as a non-option parameter. If the environment variable POSIXLY_CORRECT is set, or if the short option string started with a '+', all remaining parameters are interpreted as non-option parameters as soon as the first non-option parameter is found.
In other words, if you want to pass in a parameter like --Hello
,
you need to call _echo
like this:
_echo -- --Hello
The --
tells getopt that any following parameters should not be interpreted as options, even if they happen to look like one.
So the examples in your script would look like:
_echo "--" # OK
_echo "Hello" # OK
_echo "Hello--" # OK
_echo "-" # OK
_echo -- "---------------" # Error
_echo -- "---" # Error
_echo -- "--Hello" #Error
_echo -- "-Hello" #Error
This is a common convention for many command line programs.
As you spotted, there were problems with your implementation of _echo
. Here's a typical structure for parsing options with getopt
:
function _echo()
{
options=$(getopt -q -o t -- "$@")
if [ "$?" -ne 0 ]; then
echo "ERROR: incorrect options in $@"
return 1
fi
eval set -- "$options"
while [ "$#" -gt 0 ]; do
case $1 in
(-t) echo "got -t"
shift
;;
(--) shift
break
;;
(-*) echo "unknown option: $1"
return 1
;;
(*) break
;;
esac
done
msg=$1
echo "message is: $msg"
}
# Calling function _echo() without passing any option (sample):
_echo "--"
_echo "Hello"
_echo "Hello--"
_echo "-"
_echo -- "---------------"
_echo -- "---"
_echo -- "--Hello"
_echo -- "-Hello"
_echo -t -- "-Hello"
Upvotes: 1