简体   繁体   中英

Unseting a value in an associative bash array when the key contains a quote

I have a bash script that uses filenames as keys in an associative array. Some of the filenames have quotes in them and I can't seem to find any way to unset them.

Here's an example replicating the problem from the terminal:

$ declare -A x
$ y="key with spaces"
$ z="key with spaces and ' quote"
$ x[$y]=5   # this works fine
$ x[$z]=44  # as does this
$ echo "${x[$y]}" "${x[$z]}" # no problems here
5 44
$ unset x["$y"] # works
$ unset x["$z"] # does not work
bash: unset: `x[key with spaces and ' quote]': not a valid identifier
$ echo "${x[$y]}" "${x[$z]}" # second key was not deleted
 44

The file names processed in my script are arbitrary and need to work regardless of what characters they have in them (within reason, at least needs to work with printable characters.) The unset is used to clear a flag on files with certain properties.

How can I get bash to unset these particular keys when they might contain quote symbols?

I find this works for me:

unset 'x[$z]'

This works for other special characters:

$ y="key with spaces"
$ v="\$ ' \" @ # * & \`"
$ x[$y]=5
$ x[$v]=10
$ echo ${x[*]}
5 10
$ unset 'x[$v]'
$ echo ${x[*]}
5

This is the case where single quotes around associative array key work as well so this should work:

$> declare -p x
declare -A x='(["key with spaces and '\'' quote"]="44" )'

$> unset x['$z']

$> declare -p x
declare -A x='()'

It may be a bug (at the very least, it is inconvenient). Until a fix is available, you can work around this by getting a shell-quoted version of $z with

$ unset x["$(printf '%q' "$z")"]

In bash 4.4, this can more briefly be written as

$ unset x["${z@Q}"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM