Here is a bash3 associative array hack which satisfies:
- pure bash (no fork/exec)
- no subshell
- constant time fetch (in terms of number of keys)
- any metachars allowed in keys
The basic idea is to encode keys by substituting non-identifier chars with their hex value, and then use the sanitized key (with a name prefix) as a bash local var, leveraging the constant time bash name lookup.
enc-key()
{
    local key="${1}"  varname="${2:-_rval}"  prefix="${3:-_ENCKEY_}"
    local i  converted
    local -a enc_parts  convert
    local re='^([[:alnum:]]*)([^[:alnum:]]+)(.*)'
    local nonalnum
    enc_parts+=( "${prefix}" )
    while [[ $key =~ $re ]]; do
        enc_parts+=( "${BASH_REMATCH[1]}" )
        nonalnum="${BASH_REMATCH[2]}"
        key="${BASH_REMATCH[3]}"
        convert=()
        for (( i = 0; i < ${#nonalnum}; i++ )); do
            # leading ' in string signals printf to covert char to ascii
            convert+=( "'${nonalnum:$i:1}" )
        done
        printf -v converted "_%x" "${convert[@]}"
        enc_parts+=( "${converted}" )
    done
    enc_parts+=( "${key}" )
    printf -v $varname "%s" "${enc_parts[@]}"
    echo "DEBUG: final key: ${!varname}"
    return 0
}
To store:
    local key
    enc-key 'my-fine-key!' key
    local "${key}=value"
Fetch (before exiting function scope of the store):
    enc-key 'some other key' key
    fetched="${!key}"
Note that the second arg of enc-key is the name of the var into which enc-key will store the sanitized key.
The question: is there a way to do the encoding that does not involve character based traversal with many re matches along the way? Either some printf magic or var sub voodoo?
 
    