I have the following boilerplate for creating a shell script.
parse_debug_options() detects non-logic options such as -h, --help, --trace, or --verbose.
It appends the rest of the options and arguments for the main logic of a script to the global _logic_args variable.
main() calls parse_debug_options() first and then does set -- "${_logic_args[@]}" to modify $@.
I wish to eliminate global variables, especially mutable ones.
However, using set -- inside parse_debug_options() doesn't modify the global $@ and I needed to add global _logic_args shared between parse_debug_options() and main().
Is it possible to remove _logic_args and modify the script-wide $@ from the inside of a function?
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
declare -a _logic_args=()
function usage() {
cat <<EOF >&2
DESCRIPTION
Usage:
${0##*/} [options] [arguments]
Options:
Arguments:
Debug Options:
-h, --help Show this help message and exit
--trace Enable tracing (set -o xtrace)
EOF
}
function parse_debug_options() {
for arg in "$@"; do
case "$arg" in
-h | --help)
usage
exit 0
;;
--trace)
echo "Tracing enabled for ${0##*/}" >&2
set -o xtrace
;;
*)
_logic_args =("$arg")
;;
esac
done
}
function main() {
parse_debug_options "$@"
set -- "${_logic_args[@]}"
true
}
main "$@"
CodePudding user response:
There really isn't any way to do that; $@ is automatically local to each function.
If you want to force it, have your function emit the result to standard output, and do something like
set -- $(your function)
in the global scope.
CodePudding user response:
It's not possible to use global $@ in a function.
Alternately, I use the following code (adapted for you).
But after, I never use global "$@", I use global_params variable.
#! /usr/bin/env bash
function modify_params () {
local -n local_params=$1
local -a new_local_params=()
local p=
# echo "${FUNCNAME[0]}: ${local_params[*]@A}'"
for p in "${local_params[@]}"; do
case "$p" in
-h|--help)
echo "Help"
exit
;;
-x|--trace)
echo "Tracing enabled for ${0##*/}" >&2
set -o xtrace
;;
*)
new_local_params =("${p}")
;;
esac
done
local_params=("${new_local_params[@]}")
}
declare -a global_params=("${@}")
shift $#
modify_params global_params
declare -r global_params
echo "global: ${global_params[*]@A}"
