I have a script with a long list of OPTIONAL arguments. some have associated values.
Such as:
.script --first 2012-12-25 --last 2012-12-26 --copy --remove
.script --first 2012-12-25
Thus the following case statement:
for arg in "$@"
do
case $arg in
"--first" )
START_DATE=$arg;;
"--last" )
END_DATE=$arg;;
"--copy" )
COPY=true;;
"--remove" )
REMOVE=true;;
# ... and so on
esac
done
My problem:
that needs a increment $arg+1
type statement to get the following arg (in some cases).
How is that possible?
I'm also happy to do a substring such .script --first2012-12-25 --last2012-12-26
and not sure how to proceed there.
You can allow both --a=arg or -a arg options with a little more work:
START_DATE="$(date '+%Y-%m-%d')";
LAST_DATE="$(date '+%Y-%m-%d')";
while [[ $# -gt 0 ]] && [[ "$1" == "--"* ]] ;
do
opt="$1";
shift; #expose next argument
case "$opt" in
"--" ) break 2;;
"--first" )
START_DATE="$1"; shift;;
"--first="* ) # alternate format: --first=date
START_DATE="${opt#*=}";;
"--last" )
LAST_DATE="$1"; shift;;
"--last="* )
LAST_DATE="${opt#*=}";;
"--copy" )
COPY=true;;
"--remove" )
REMOVE=true;;
"--optional" )
OPTIONAL="$optional_default";; #set to some default value
"--optional=*" )
OPTIONAL="${opt#*=}";; #take argument
*) echo >&2 "Invalid option: $@"; exit 1;;
esac
done
Note the --optional argument uses a default value if "=" is not used, else it sets the value in the normal way.
Use shift
in the end of each case
statement.
Quote from a bash
manual:
shift [n]
The positional parameters from n+1 ... are renamed to $1
.... Parameters represented by the numbers $# down to $#-n+1 are
unset. n must be a non-negative number less than or equal to $#. If
n is 0, no parameters are changed. If n is not given, it is assumed
to be 1. If n is greater than $#, the positional parameters are not
changed. The return status is greater than zero if n is greater than
$# or less than zero; otherwise 0.
If you have more than one option, and especially options with values mixed with options without values, let getopts do the work for you.
getopts cannot have optional arguments it seems. otherwise great.
my solution
loop the $@
and setting a variable equal to x=$arg
do the case switch on that variable (rather than arg)
that worked fine for arguments of the type --startdate 2012-12-25 --enddate 2012-12-29
but did not work for --remove
that has no following argument.
therefore tack on stuff (unlikely argument) onto the arg string.
leaving the following
argc="$@ jabberwhocky"
echo $argc
x=0
# x=0 for unset variable
for arg in $argc
do
case $x in
"--start" )
STARTDATE=$arg ;;
"--end" )
ENDDATE=$arg ;;
"--copy" )
COPY=true;;
"--remove" )
REMOVE=true;;
... and so on....
esac
x=$arg
done
$@
is an array, & not a simple variable.
You can capture it to a local variable as x=("$@")
& then use array x with indices as 0 to ($# - 1)
.
To access individual elements, use ${x[$i]}
. You can NOT directly use ${@[$i]}
, however.
So instead of for arg in "$@"
loop, you will have i=0; while [ $i -lt $# ]; do
loop.