0

I'm trying out the associative arrays in bash 5.1.16 by loading a file into a hash table like so but it doesn't work if the file values are in quotes it returns null:

#!/bin/bash -e

declare -A dict

while read key; do
    dict[$key]=$key
done < test2.txt

echo "This doesn't work ${dict[a]} ${dict[b]}"

test2.txt file being:

"a"
"b"
"c"

But if I remove the quotes in test2.txt it works fine. But what I can't understand is if I assign them manually with and without quotes both ways work.

#!/bin/bash -e

declare -A dict

dict[f]="f"
dict["g"]="g"

echo "This works ${dict["f"]} ${dict["g"]}"

My understanding from other SO answers is that the keys shouldn't be quoted but as you see in the previous example they work with quotes. So how can I load the file if the keys have quotes or the should have them removed before loading?

PerseP
  • 1,177
  • 2
  • 14
  • 22
  • 3
    `echo "a"` and `key='"a"'; echo $key` is not the same in the same way. – KamilCuk Feb 13 '23 at 12:27
  • 2
    When quotes are read from the file, they're treated as part of the data, so `dict[$key]=$key` will create an array entry that contains literal quote characters as part of the key (and value). In `dict["g"]="g"`, on the other hand, the quotes are treated as shell syntax *around* the key and value, not actually as part of the key and value. If you don't want the quotes treated as part of the data, you need to remove them yourself. – Gordon Davisson Feb 13 '23 at 12:55
  • 1
    Or conversely `echo "This does work ${dict[\"a\"]} ${dict[\"b\"]}"` – tripleee Feb 13 '23 at 13:08
  • Does this answer your question? [Why does shell ignore quoting characters in arguments passed to it through variables?](https://stackoverflow.com/questions/12136948/why-does-shell-ignore-quoting-characters-in-arguments-passed-to-it-through-varia) – tjm3772 Feb 13 '23 at 15:37

1 Answers1

3

The shell uses " to signify that word-splitting should not occur in some contexts where parameter expansion occurs. The double-quotes are not treated as part of the data that they surround.

When reading data from the file, the " are part of the data itself, in the same way that commands are not executed.

cat >test3.txt <<'EOD'
echo   hello $world
"a"
a
EOD

declare -A dict2

while read key; do
    dict2[$key]=$key
done < test3.txt

dict2[f]="f"
dict2["g"]="g"

dict2[\"h\"]=\"h\"
dict2['"i"']='"i"'

declare -p dict2

outputs (wrapped/indented for clarity here):

declare -A dict2=(
    ["echo   hello \$world"]="echo   hello \$world"
    [g]="g"
    [f]="f"
    [a]="a"
    ["\"a\""]="\"a\""
    ["\"i\""]="\"i\""
    ["\"h\""]="\"h\""
)

More precisely, from the bash manual, Quoting:

Quoting is used to remove the special meaning of certain characters or words to the shell. Quoting can be used to disable special treatment for special characters, to prevent reserved words from being recognized as such, and to prevent parameter expansion.

Note that read when used without -r may alter the data read, and if given multiple variables will perform word-splitting.

jhnc
  • 11,310
  • 1
  • 9
  • 26
  • I see `declare -p` saves us from looping to see the contents from the dictionary – PerseP Feb 13 '23 at 13:43
  • @PerseP Yes. It is presented as a command that allows recreating the content. Double-quotes, backslashes,etc are only added where necessary. – jhnc Feb 13 '23 at 13:45