Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash argument case for args in $@

Tags:

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.

like image 512
Gabe Rainbow Avatar asked Dec 27 '12 23:12

Gabe Rainbow


People also ask

What does $@ do in bash script?

Symbol: $# The symbol $# is used to retrieve the length or the number of arguments passed via the command line. When the symbol $@ or simply $1, $2, etc., is used, we ask for command-line input and store their values in a variable.

What is $@ in a shell script?

$@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.

What is the difference between $@ and $* in bash?

There is no difference if you do not put $* or $@ in quotes. But if you put them inside quotes (which you should, as a general good practice), then $@ will pass your parameters as separate parameters, whereas $* will just pass all params as a single parameter.


2 Answers

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.

like image 133
Gilbert Avatar answered Jan 17 '23 19:01

Gilbert


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.

like image 38
favoretti Avatar answered Jan 17 '23 20:01

favoretti