doak
doak

Reputation: 955

Why can't an associative Bash array be assigned with an array?

According to man bash it is possible to assign an associative array with a flat list of key-value pairs:

[…] or a list of words that is interpreted as a sequence of alternating keys and values: name=( key1 value1 key2 value2 ...)

This does work, but it does not work to use an array to get these "alternating keys and values": name=( "${someArray[@]}" )

Consider this example:

#!/usr/bin/env bash

set -u

#declare -A map=(one ONE two TWO)
array=(one ONE two TWO)
declare -A map=("${array[@]}")
# Workaround with `eval`:
#eval "declare -A map=(${array[@]@Q})"

echo "KEYS:"
printf '    %s\n' "${!map[@]}"
echo "VALUES:"
printf '    %s\n' "${map[@]}"

echo "${#map[@]}"

Actual output:

KEYS:
    one ONE two TWO
VALUES:
    

Expected output:

KEYS:
    two
    one
VALUES:
    TWO
    ONE

Why is that so?

Upvotes: 6

Views: 159

Answers (1)

pmf
pmf

Reputation: 36058

Include the array parens in the quoted string to preserve the whitespace between items for the declaration. Also, if keys or values themselves contain whitespace, use @Q to quote each item:

array=(one 'O NE' 'tw o' TWO)
declare -A map="(${array[@]@Q})"

echo "KEYS:"
printf '    %s\n' "${!map[@]}"
echo "VALUES:"
printf '    %s\n' "${map[@]}"

echo "${#map[@]}"
KEYS:
    one
    tw o
VALUES:
    O NE
    TWO
2

Tested with GNU bash 5.2.21

Upvotes: 6

Related Questions