Home > Enterprise >  How do I modify global $@ from the inside of a function?
How do I modify global $@ from the inside of a function?

Time:12-27

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}"
  • Related