A generic way of overriding properties declarations & definitionsat the command-line
am 25.10.2007 02:50:41 von Nicolas GirardHi, =
I'm looking for some help with the following problem.
I would like to find a generic way of overriding declarations &
definitions of a program's properties at the command-line,
whithout interfering with the rest of the program flow.
As an example, lets us consider a bash program which declares a set of
properties prop1, prop2, ...,
and gives a default value to some of them:
#!/usr/bin/env bash
...
prop1=value1
...
[ -n "${prop2+X}" ] && echo prop2 set || echo prop2 not set
...
prop3=value3
...
Then, I would like to be able to redefine any of propN using the
following syntax:
./prog -Dprop1=myvalue1 -Dprop2
Typing the above command would make prop2 to be declared in prog, and
would give to prop1 another value than the default one.
Regarding the handling of command-line options, two important constraints
should be respected:
1. the -D
options controlling the program flow; thus the following example
should be valid:
./prog -u -Dprop1=myvalue1 -v=3 -Dprop2
2. even if properties names should not contain spaces, there may
be spaces in their values or elsewhere in the command-line, such
as:
./prog -u -Dprop1="/path/to my file" -v="1 2 3" -Dprop2
As for the implementation, I'd wish the -D
be handled by a single, generic, resuseable function, let's call it
"parse_Dopts", transparently from the rest of the program:
#!/usr/bin/env bash
parse_Dopts $*
# rest of the program, using getopts or whatever
# to parse the command-line options
...
I came to this early implementation of parse_Dopts and I'm stuggling with
2 difficulties A and B:
function parse_Dopts()
{
local opt,prop,tmp,value
for opt in $*; do # A: what about spaces ?
if [[ ${opt:0:2} = '-D' ]]; then
tmp=${opt:2} # Suppress the leading '-D'
prop=${tmp%%=*} # Extract the property name
if [[ "${tmp}" = *=* ]]; then #
value=${tmp##*=}
else
value=""
fi
eval $prop="$value"
else
other_options[${#other_options[@]}]="$opt"
fi
done
#set -- ${other_options[@]} # B: How to update the global positional
# parameters without leaving the
# function ?
}
The two difficulties which brought me here are:
A. right now the function does its job when its arguments don't contain
spaces, but fails otherwise ;
B. it would be very nice if the function could itself update the global
positional parameters (by removing the -D
rest of the program could make use of getopts without problems, in
order to process the other command-line options. But right now
I couldn't find a way of doing this *inside* the function.
Voila. I'd be grateful for *any* comments or suggestions, and thanks
anyway for reading !
Cheers,
Nicolas