Here's a pure Bash possibility:
set_to_default() {
# $1 is variable name
# $2, ... are arguments
# If variable pointed by $1 is set then nothing happens
# Otherwise, variable with name $1 is set to the value determined
# by the subsequent parameters:
# * if only $2 is present, variable is set to that value
# * if $2, $3... are present, then variable is set to an
# array with fields $2, $3, ...
(($#<2)) && return 1
local varname=$1
declare -p "$varname" &>/dev/null && return 0
shift
if (( $#==1 )); then
printf -v "$varname" '%s' "$1"
else
declare -ag "$varname=( \"\$@\" )"
fi
}
Basic check:
$ variable_1=( 1.00 2.00 3.00 )
$ set_to_default variable_1 "a"
$ set_to_default variable_2 "a" "b" "b c"
$ set_to_default variable_3 "/filepath with spaces/bash will mess up/"
$ declare -p "${!variable_@}"
declare -a variable_1='([0]="1.00" [1]="2.00" [2]="3.00")'
declare -a variable_2='([0]="a" [1]="b" [2]="b c")'
declare -- variable_3="/filepath with spaces/bash will mess up/"
Also works with embedded newlines and any funny character you can imagine:
$ set_to_default banana $'a newline\nhere' '*' '' ' '
$ declare -p banana
declare -a banana='([0]="a newline
here" [1]="*" [2]="" [3]=" ")'
If you want to set an array with only one field, first declare it as an array. Compare:
$ unset banana
$ set_to_default banana gorilla
$ declare -p banana
declare -- banana="gorilla"
$ unset banana
$ declare -a banana
$ set_to_default banana gorilla
$ declare -p banana
declare -a banana='([0]="gorilla")'
Bash<4
Wait, I just read in a comment that you have Bash 3.2, so this won't work because of the -g
flag to declare
. Then you'll have to explicit the loop:
set_to_default() {
# $1 is variable name
# $2, ... are arguments
# If variable pointed by $1 is set then nothing happens
# Otherwise, variable with name $1 is set to the value determined
# by the subsequent parameters:
# * if only $2 is present, variable is set to that value
# * if $2, $3... are present, then variable is set to an
# array with fields $2, $3, ...
(($#<2)) && return 1
local varname=$1 i
declare -p "$varname" &>/dev/null && return 0
shift
if (( $#==1 )); then
printf -v "$varname" '%s' "$1"
else
i=0
while IFS= read -r -d '' "$varname[$i]"; do ((++i)); done < <(printf '%s\0' "$@")
fi
}