Hi. I have a piece of code that reads and parses command line options. I'd like to alter it slightly to read from a string (that's set elsewhere in the script) rather than directly from the command line (arg). Can somebody show me how to do this? Many thanks.
My code is as follows:
typeset flags_args=''
for arg; do
case $arg in
-version ) flags_args="${flags_args} -t" ;;
-host ) flags_args="${flags_args} -r" ;;
-debug ) flags_args="${flags_args} -d" ;;
* ) flags_args="${flags_args} $arg" ;;
esac
done
set -- ${flags_args}
while getopts :t:r:d args; do
case $args in
t) typeset VERSION="$OPTARG" ;;
r) typeset HOST="$OPTARG" ;;
d) typeset DEBUG="true"; typeset DEBUG="DEBUG" ;;
*) print "Invalid option specified." ;;
esac
done
shift $((OPTIND-1));
Instead of reading the arguments from command line I'd like the code to read from the following variable that's set inside the KSH script:
Many versions of the Korn shell include a getopts that supports both long options and short options (although support for long options isn't always mentioned in the ksh man page). If you could introduce your long options with -- instead of a single - , you might want to try the following replacement for your code:
while getopts ':t:(version)r:(host)d(debug)' args; do
case $args in
t) typeset VERSION="$OPTARG" ;;
r) typeset HOST="$OPTARG" ;;
d) typeset DEBUG="DEBUG" ;;
*) print "Invalid option specified." ;;
esac
done
shift $((OPTIND-1));
printf 'DEBUG has been set to "%s"\n' "$DEBUG"
printf 'HOST has been set to "%s"\n' "$HOST"
printf 'VERSION has been set to "%s"\n' "$VERSION"
and see what happens when you invoke it with:
script_name --version 99 --host=testhost
and:
script_name -t 98.6 -rmyhost --debug
When I try the above two commands with ksh on macOS High Sierra (version 10.13.1), I get the output:
DEBUG has been set to ""
HOST has been set to "testhost"
VERSION has been set to "99"
and:
DEBUG has been set to "DEBUG"
HOST has been set to "myhost"
VERSION has been set to "98.6"
You can also use a subfunction to parse the command line and feed it the string:
parse_cmd ()
{
while getopts :t:r:d args; do
case $args in
t) typeset VERSION="$OPTARG" ;;
r) typeset HOST="$OPTARG" ;;
d) typeset DEBUG="true"; typeset DEBUG="DEBUG" ;;
*) print "Invalid option specified." ;;
esac
done
shift $((OPTIND-1));
return 0
}
...
# main()
STR="<your arguments here in the same form as parameters from stdin>"
parse_cmd $STR # process opts and args from STR
parse_cmd $* # process opts and args from stdin
exit 0
Note that if you use a subfunction like above you need to get the parsed values out of the function somehow, because the variables in it are now local to the function.
Hi bakunin,
Note that typeset is not in the standards and the way it behaves varies some between shells. In bash declaring a variable with local or with typeset makes the variable definition have a scope that is local to the function and values assigned to such variables are not visible when the function returns to its caller. But, a variable that is not declared with local nor with typeset has a global scope and if such a variable is assigned a value inside a function, the value assigned in the function will still be visible when the variable is expanded outside of the function.
In ksh , declaring a variable with typeset in a function does not give it a local scope; it has a global scope. The ksh command language does not have a local keyword or built-in function.
The values assigned to VERSION , HOST , and DEBUG in the function parse_cmd can be found after parse_cmd completes by just expanding those variables with $VERSION , $HOST , and $DEBUG .
Note that I removed the 1st assignment to DEBUG . I don't see any reason to assign it the value TRUE and then immediately assign another value ( DEBUG ) to it.