helpThe GNU Bourne-Again SHell - Support: sr #109139, Unset on certain elements of...


sr #109139: Unset on certain elements of associative arrays does not work as expected

Submitted by:  Maxxim <maxxim>
Submitted on:  Sat 10 Sep 2016 05:34:35 PM UTC  
Category: NonePriority: 5 - Normal
Severity: 3 - NormalStatus: Postponed
Privacy: PublicAssigned to: None
Open/Closed: OpenOperating System: GNU/Linux

Add a New Comment(Rich Markup)

You are not logged in

Please log in, so followups can be emailed to you.


Sun 16 Oct 2016 09:13:11 PM UTC, comment #4:

1. Probably not. There were several bug fixes regarding associative array subscript parsing between bash-4.3 and bash-4.4.

2. I have considered it, but there is many years' worth of backwards compatibility to consider as well.

Chet Ramey <chet>
Project Administrator
Sat 01 Oct 2016 02:46:07 PM UTC, comment #3:

Thank you for your reply. Two questions remain:

1) Is there a way to make the example work in Bash 4.3? I couldn't quite figure that out from the conversation you referred to. (Bash 4.4 is not yet stable in my distribution as of writing this)

2) Even if that works, it's not intuitive at all. Isn't it possible to change the way unset works to a more intuitive, let's say 'developer-friendly' way?

Maxxim <maxxim>
Sun 25 Sep 2016 04:26:58 PM UTC, comment #2:

When bash resolves an array reference, it dynamically expands
the subscript as part of obtaining its value. There is a good
posting on help-bash explaining why bash does this:

My reply points out that you need to quote the brackets to be
safe, since the word is subject to filename expansion. The
unset builtin assumes that the word has been quoted and that the
subscript needs to be expanded as part of figuring out which
element to unset.

You can make your example work in bash-4.4 by single-quoting the
arguments to unset and assuming that the subscript will be run
through the usual set of word expansions:

unset 'testdict[\"hey you\"]'

Chet Ramey <chet>
Project Administrator
Mon 12 Sep 2016 01:10:04 PM UTC, comment #1:

There seem to be countless other examples, e.g.

# declare -A testdict=( ["\"hey you\""]="test" )
# unset testdict["\"hey you\""]
bash: unset: testdict["hey you"]: bad array subscript
# unset testdict['"hey you"']
bash: unset: testdict["hey you"]: bad array subscript

which suggests that the way unset interprets associative arrays is completely flawed.

Maxxim <maxxim>
Sat 10 Sep 2016 05:34:35 PM UTC, original submission:

While working on a project that uses associative arrays to store data, I discovered the following unexpected behaviour:

# declare -A testdict=( ["[]"]="" )
# unset testdict["[]"]
# echo ${!testdict[@]}

The unset command seems to have no effect. After trying all variations of the unset command (quoting, escaping etc.) I could think of, I finally found one that works:

# unset testdict["\[]"]

Although that solves that specific problem, I found another item which can't be unset no matter what unset variation I tried:

# declare -A testdict=( ["]"]="" )

I think it's worth mentioning that the problem only seems to occur with square brackets - parentheses, braces etc. don't cause any trouble.

I'm using Bash 4.3_p42 on Gentoo Linux (x64).

Maxxim <maxxim>


(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach File(s):

No files currently attached


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -unavailable- added by chet (Posted a comment)
  • -unavailable- added by maxxim (Submitted the item)

    Do you think this task is very important?
    If so, you can click here to add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.


    Please enter the title of George Orwell's famous dystopian book (it's a date):



    Follows 1 latest change.

    Date Changed By Updated Field Previous Value => Replaced By
    Sun 25 Sep 2016 04:26:58 PM UTCchetStatusNone=>Postponed

    Back to the top

    Powered by Savane 3.1-cleanup1