Assigning arrays to variables in Bash script seems rather complicated:
a=("a" "b" "c") b=$a echo ${a[0]} echo ${a[1]} echo ${b[0]} echo ${b[1]}
leads to
a b a
instead of
a b a b
Why? How can I fix it?
Note: when copying associative arrays, the destination must already exist as an associative array. If not, array_copy() will create it as a standard array and try to interpret the key names from the associative source as arithmetic variable names, with ugly results.
To append element(s) to an array in Bash, use += operator. This operator takes array as left operand and the element(s) as right operand. The element(s) must be enclosed in parenthesis. We can specify one or more elements in the parenthesis to append to the given array.
If you want to copy a variable that holds an array to another name, you do it like this:
a=('a' 'b' 'c') b=( "${a[@]}" )
If a
is an array, $a
expands to the first element in the array. That is why b
in your example only has one value. In bash, variables that refer to arrays aren't assignable like pointers would be in C++ or Java. Instead variables expand (as in Parameter Expansion) into strings and those strings are copied and associated with the variable being assigned.
To copy a sparse array that contains values with spaces, the array must be copied one element at a time by the indices - which can be obtained with ${!a[@]}.
declare -a b=() for i in ${!a[@]}; do b[$i]="${a[$i]}" done
From the bash man page:
It is possible to obtain the keys (indices) of an array as well as the values. ${!name[@]} and ${!name[*]} expand to the indices assigned in array variable name. The treatment when in double quotes is similar to the expansion of the special parameters @ and * within double quotes.
Here's a script you can test on your own:
#!/bin/bash declare -a a=(); a[1]='red hat' a[3]='fedora core' declare -a b=(); # Copy method that works for sparse arrays with spaces in the values. for i in ${!a[@]}; do b[$i]="${a[$i]}" done # does not work, but as LeVar Burton says ... #b=("${a[@]}") echo a indicies: ${!a[@]} echo b indicies: ${!b[@]} echo "values in b:" for u in "${b[@]}"; do echo $u done
Prints:
a indicies: 1 3 b indicies: 1 3 # or 0 1 with line uncommented values in b: red hat fedora core
This also works for associative arrays in bash 4, if you use declare -A
(with capital A instead of lower case) when declaring the arrays.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With