Indirect variable references in Bash 4.3

Sept. 5, 2018, 7:58 a.m.

There is a way to declare (-n) a variable in Bash as a reference to another variable (kind of pointer). This allows us to pass multiple arrays to functions or create utility functions like:

# Check if variable is set. Will return true even when the value is an empty string.
# Usage: is_set VAR_NAME
is_set () {
    declare -n __var="$1"
    [[ "${__var+set}" = 'set' ]]
}

or

# Translate characters in a string
# Usage: translate STR FROM_CHARS TO_CHARS
translate () {
    declare str="$1"
    declare -n __from="$2"
    declare -n __to="$3"
    declare i

    [[ "${#__from[@]}" = "${#__to[@]}" ]] || return 1

    for i in "${!__from[@]}"; do
        str="${str//"${__from[$i]}"/"${__to[$i]}"}"
    done

    printf '%s\n' "$str"
}
$ declare -a from=(a b)
$ declare -a to=(c d)

$ translate "abc" from to
cdc

or

pushopts () {
    declare -n __opts="$1"
    readarray -t __opts < <(shopt -po)
}

popopts () {
    declare -n __opts="$1"
    declare cmd
    for cmd in "${__opts[@]}"; do
        eval "$cmd"
    done
}
$ set -e
$ pushopts BACKUP
$ set +e
$ popopts BACKUP
$ shopt -po errexit
set -o errexit