I am trying to process command line arguments using getopts in bash. One of the requirements is for the processing of an arbitrary number of option arguments (without the use of quotes).
1st example (only grabs the 1st argument)
madcap:~/projects$ ./getoptz.sh -s a b c
-s was triggered
Argument: a
2nd example (I want it to behave like this but without needing to quote the argument"
madcap:~/projects$ ./getoptz.sh -s "a b c"
-s was triggered
Argument: a b c
Is there a way to do this?
Here's the code I have now:
#!/bin/bash
while getopts ":s:" opt; do
case $opt in
s) echo "-s was triggered" >&2
args="$OPTARG"
echo "Argument: $args"
;;
\?) echo "Invalid option: -$OPTARG" >&2
;;
:) echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
I think what you want is to get a list of values from a single option. For that, you can repeat the option as many times as needed, and add it's argument to an array.
#!/bin/bash
while getopts "m:" opt; do
case $opt in
m) multi+=("$OPTARG");;
#...
esac
done
shift $((OPTIND -1))
echo "The first value of the array 'multi' is '$multi'"
echo "The whole list of values is '${multi[@]}'"
echo "Or:"
for val in "${multi[@]}"; do
echo " - $val"
done
The output would be:
$ /tmp/t
The first value of the array 'multi' is ''
The whole list of values is ''
Or:
$ /tmp/t -m "one arg with spaces"
The first value of the array 'multi' is 'one arg with spaces'
The whole list of values is 'one arg with spaces'
Or:
- one arg with spaces
$ /tmp/t -m one -m "second argument" -m three
The first value of the array 'multi' is 'one'
The whole list of values is 'one second argument three'
Or:
- one
- second argument
- three
This's my way to do this with a user-defined-function: getopts-extra
.
function getopts-extra () {
declare i=1
# if the next argument is not an option, then append it to array OPTARG
while [[ ${OPTIND} -le $# && ${!OPTIND:0:1} != '-' ]]; do
OPTARG[i]=${!OPTIND}
let i++ OPTIND++
done
}
# Use it within the context of `getopts`:
while getopts s: opt; do
case $opt in
s) getopts-extra "$@"
args=( "${OPTARG[@]}" )
esac
done
The full example of getoptz.sh:
#!/usr/bin/env bash
function getopts-extra () {
declare i=1
# if the next argument is not an option, then append it to array OPTARG
while [[ ${OPTIND} -le $# && ${!OPTIND:0:1} != '-' ]]; do
OPTARG[i]=${!OPTIND}
let i++ OPTIND++
done
}
function main () {
declare args
declare OPTIND OPTARG opt
while getopts :s: opt; do
case $opt in
s) getopts-extra "$@"
args=( "${OPTARG[@]}" )
;;
\?) echo "Invalid option: -$OPTARG" >&2
;;
:) echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
declare i
for i in "${!args[@]}"; do
echo "args[$i]: ${args[i]}"
done
}
main "$@"
exit
Test:
bash getoptz.sh -s a b c
Output:
args[0]: a
args[1]: b
args[2]: c
This function is a part of the bash lib called xsh-lib/core, available at the syntax xsh /util/getopts/extra
.
You can parse the command-line arguments yourself, but the getopts
command cannot be configured to recognize multiple arguments to a single option. fedorqui's recommendation is a good alternative.
Here is one way of parsing the option yourself:
while [[ "$*" ]]; do
if [[ $1 = "-s" ]]; then
# -s takes three arguments
args="$2 $3 $4"
echo "-s got $args"
shift 4
fi
done
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With