Im trying to pass arguments to a script i wrote, but cant get it right.
What i want is one mandatory argument without a flag, and two optional arguments with flags, so it can be called like this:
./myscript mandatory_arg -b opt_arg -a opt_arg
or
./myscript mandatory_arg -a opt_arg
./myscript mandatory_arg -b opt_arg
I looked into getopts and got this:
while getopts b:a: option
do
case "${option}"
in
b) MERGE_BRANCH=${OPTARG};;
a) ACTION=${OPTARG};;
esac
done
if "1ドル" = ""; then
exit
fi
echo "1ドル"
echo "$MERGE_BRANCH"
echo "$ACTION"
But it does not work at all.
asked Feb 3, 2017 at 8:59
A.Jac
1,7234 gold badges21 silver badges25 bronze badges
1 Answer 1
Assuming that your mandatory argument appears last, then you should try the following code: [comments inline]
OPTIND=1
while getopts "b:a:" option
do
case "${option}"
in
b) MERGE_BRANCH=${OPTARG};;
a) ACTION=${OPTARG};;
esac
done
# reset positional arguments to include only those that have not
# been parsed by getopts
shift $((OPTIND-1))
[ "1ドル" = "--" ] && shift
# test: there is at least one more argument left
(( 1 <= ${#} )) || { echo "missing mandatory argument" 2>&1 ; exit 1; };
echo "1ドル"
echo "$MERGE_BRANCH"
echo "$ACTION"
The result:
~$ ./test.sh -b B -a A test
test
B
A
~$ ./tes.sh -b B -a A
missing mandatory argument
If you really want the mandatory argument to appear first, then you can do the following thing:
MANDATORY="${1}"
[[ "${MANDATORY}" =~ -.* ]] && { echo "missing or invalid mandatory argument" 2>&1; exit 1; };
shift # or, instead of using `shift`, you can set OPTIND=2 in the next line
OPTIND=1
while getopts "b:a:" option
do
case "${option}"
in
b) MERGE_BRANCH=${OPTARG};;
a) ACTION=${OPTARG};;
esac
done
# reset positional arguments to include only those that have not
# been parsed by getopts
shift $((OPTIND-1))
[ "1ドル" = "--" ] && shift
echo "$MANDATORY"
echo "$MERGE_BRANCH"
echo "$ACTION"
The result is the following:
~$ ./test.sh test -b B -a A
test
B
A
~$ ./tes.sh -b B -a A
missing or invalid mandatory argument
answered Feb 3, 2017 at 9:04
Patrick Trentin
7,3723 gold badges26 silver badges44 bronze badges
Sign up to request clarification or add additional context in comments.
5 Comments
A.Jac
When trying to run this it prints out the mandatory argument and then "" for the optionals, if i run without the mandatory it replies with "missing mandatory argument"
A.Jac
What is the reason for not recommending having the mandatory argument first? and i think something is missing from the last edit
Patrick Trentin
@A.Jac it's just a matter of convention and personal taste
Patrick Trentin
@A.Jac Assume that your mandatory argument is the name of a file, and that your file name is
-test, with the former code you can write ./test..sh -b B -a A -- -test and have your program work correctly, whereas with the last code you won't be able to parse it: -- is used to make getopt stop looking for options, but A) -b B -a A won't be recognized as options B) -- will fail the test [[ ${MANDATORY} =~ -.* ]]Patrick Trentin
Anyway I removed my personal opinions from the answer, because clearly there are workarounds for the issues I see with this approach, it is only a matter of implementing them with some more extra code.
lang-bash