Easy commandline argument parsing in shell script
March 2, 2010 1 Comment
Here is a fairly easy method which can parse all input arguments passed to a shell script in commandline. This block of code can be either included in top of the script or source it from an external file.
Using this code within a shell script is very simple, just needs to define a global variable named ARGS_INPUT_FORMAT and set appropriate values to it. The argument parsing code will read this variable and set appropriate inputs as well as outputs.
Set values to the variable ARGS_INPUT_FORMAT as shown below.
ARGS_INPUT_FORMAT="OPTION STRING 1|OPTION STRING 2(OPTIONAL)|OPTION STRING N(OPTIONAL):VARIABLE NAME WHICH HOLDS OPTION VALUE:DEFAULT OPTION VALUE(OPTIONAL):DEFAULT OPTION VALUE IF USED AS SWITCH(OPTIONAL)"
Example Usage
These are some examples:
ARGS_INPUT_FORMAT="--ignore-case|-i:check_case:NO:YES"
ARGS_INPUT_FORMAT="--user|-u|-U:username:-1:-1,--ignore-case|-i:ignore_case:NO:YES"
ARGS_INPUT_FORMAT="--color:bgcolor"
Some example script usages are:
./main-script.sh --ignore-case="YES"
./main-script.sh -i -u "Find Linux Help"
./main-script.sh --color="Yellow"
Now access the value of color using variable bgcolor as shown below.
echo "You have chosen $bgcolor color."
There are some advantages of this code; it is not utilizing the capabilities of an external binary but parse using shell script itself. It never shifts or alters the original arguments supplied to main script. It retains the position and count of arguments and can be re-used them inside the main script again.
Argument Parsing Code
for arg_opts in $(echo "$ARGS_INPUT_FORMAT" | tr "," " ") ; do
opt_names=$(echo "$arg_opts" | cut -d':' -f1)
opt_var=$(echo "$arg_opts" | cut -d':' -f2)
opt_def_val=$(echo "$arg_opts" | cut -d':' -f3)
opt_switch_val=$(echo "$arg_opts" | cut -d':' -f4)
eval "$opt_var=$opt_def_val"
for opt_name in $(echo "$opt_names" | tr "|" " ") ; do
arg_pos=1
while [ $arg_pos -le $# ] ; do
case "$(eval "echo $$arg_pos")" in
"$opt_name="*)
eval "$opt_var="$(echo "$(eval "echo $$arg_pos")" | sed 's/^'"$opt_name"'=//')""
ARGS_STAT[$arg_pos]=0
;;
"$opt_name")
if [ $(expr $arg_pos + 1) -le $# ] && [ $(echo "$(eval "echo $$(expr $arg_pos + 1)")" | grep -c '^-') -eq 0 ] ; then
ARGS_STAT[$arg_pos]=0
arg_pos=$(expr $arg_pos + 1)
eval "$opt_var="$(eval "echo $$arg_pos")""
else
eval "$opt_var="$opt_switch_val""
fi
ARGS_STAT[$arg_pos]=0
;;
"$opt_name"*)
eval "$opt_var="$(echo "$(eval "echo $$arg_pos")" | sed 's/^'"$opt_name"'//')""
ARGS_STAT[$arg_pos]=0
;;
*)
[ -z "${ARGS_STAT[$arg_pos]}" ] && ARGS_STAT[$arg_pos]=1
;;
esac
arg_pos=$(expr $arg_pos + 1)
done
done
done
Download the script file: [download id="5"]
Script Usage
Define a global variable as ARGS_INPUT_FORMAT and set an appropriate value as shown above. Define this variable on top of the main script.
Save the argument parsing script to an external file and source it into the main script. The same source script can be included in as many scripts wherever you need argument processing. Even the code block can be directly pasted below the global variable definition inside your main script for better portability.
About Debugging
The script initializes an array variable named ARGS_STAT and set debug values to it. If it finds an invalid argument in commandline, the corresponding array index is updated with a dirty flag “1″.
Here is a sample code which can be included in the main script to display invalid arguments supplied and their respective position numbers.
echo "**Invalid args**"
count=1
while [ $count -le $# ] ; do
if [ ${ARGS_STAT[$count]} -eq 1 ] ; then
echo "$(eval echo $$count) ($count)"
fi
count=$(expr $count + 1)
done
Download the script file: [download id="6"]
Thanks for this script! It’s very usefull.
Please add option to get no option aurgument, e.g. files in this form:
$(COMMAND) (options) FILE1 FILE2, …
Thanks,
Tal