I'm trying to move some getopts
logic to a funciton, so I can use it more than once, giving users more flexibility in the order in which they specify arguments:
print-usage() {
echo "myssh [options] <host> [options] [-- ssh-options...]" >&2
exit 1
}
extra_args=()
parse-args() {
while getopts ":hvV:" opt; do
case ${opt} in
(h) print-usage ;;
(v) extra_args+=('-L 5900:localhost:5900') ;;
(V) extra_args+=("-L $OPTARG:localhost:5900") ;;
(?) echo "Invalid option: -$OPTARG" >&2 ;;
(:) echo "Invalid option: -$OPTARG requires an argument" >&2 ;;
esac
done
echo $((OPTIND -1))
}
shift $(parse-args $@)
host=$1
shift
shift $(parse-args $@)
ssh $host $extra_args $@
My problem is that parse-args() { ... extra_args+=(...) }
doesn't affect the global variable extra_args
. I get that a sub-shell can't write to parent-scoped variables, and we should normally use stdout, but I'm already using stdout for the shift integer.
How would one normally address this problem?
optind
variable that you set in the function and then use in the main code, avoiding the command substitution entierly? Remember thatOPTIND
needs to be set to 1 at the start of the function, and that using$@
unquoted would split and glob all arguments. Also, since-L
and e.g.5900:localhost:5900
are two separate arguments, should you not add them as separate elements inextra_args
? Not really a real answer as I haven't tested anything and I'm just throwing ideas around. – Kusalananda Jun 28 '21 at 10:48