Path: csiph.com!goblin3!goblin1!goblin.stu.neva.ru!usenet.stanford.edu!not-for-mail From: Great Big Dot Newsgroups: gnu.bash.bug Subject: Indices of array variables are sometimes considered unset (or just display an error). Date: Mon, 05 Nov 2018 16:42:16 -0500 Lines: 79 Approved: bug-bash@gnu.org Message-ID: NNTP-Posting-Host: lists.gnu.org X-Trace: usenet.stanford.edu 1541455653 6586 208.118.235.17 (5 Nov 2018 22:07:33 GMT) X-Complaints-To: action@cs.stanford.edu To: bug-bash@gnu.org Envelope-to: bug-bash@gnu.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:date:message-id:user-agent:to:subject:machine:os:compiler; bh=bqEaGLocORFQfc3AAYG6XCFGdm3pCnzw3G9IlXERMx4=; b=eCyPTeVxvANM3OhZDLc14tK1hniwwuGhmbvYucWZ5SbeILbw5H4LObGymQOs/pUeH2 IXEwtk5UvlRTSnStQvdE0yGgIyHRXzTugsOK5lg2N8PZZ9zzAUOHQ+kCTvPB6Fi19V47 1CI5aZBE9X1VpHLG3IOo2Z4+mlrI/wiHVsXi2Zju3i2jkmhMkesVC84iHnFLLOF1SkAI oLSBvRybmY1mOgNCwJwLsHEY4NMgn+h7ljtlnROoWPz7A7kbxilpJj2AB57BMIeo1e9E cnXD5I8VKbYSzduJdHhm2QF+qhCt5sV14geyx9UjIUTJPk/eXPPEBl0x7uPbIuo03IfC yQHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:date:message-id:user-agent:to:subject :machine:os:compiler; bh=bqEaGLocORFQfc3AAYG6XCFGdm3pCnzw3G9IlXERMx4=; b=A0BHS2gyqmBgXWavFrqLVZbnbTXxosZQ33z7dDA/+cTk+tjvmcmJubqU+YFaJzpo+B QsGpEV44DBMm+vgAWzfGchfhqbffbypRukfcx9QtrP6EnXoXN/Vma3v8ENxyU1S0fbFR bK1hwksMBIx8k8mO4artKofy3Obrr6fiF8rO0ndCQHcMWFXqmlGTQxwCnFkPb0vERm4s HjotWMpjcpv0AOjnRi3AgW82Yfw2i0K4qL6YeR+g1plYUoMANA5/KLD5b++vvrc8P29G 1TKsTDH4kDfSMeIJ7we+zDbEqkHb8No38OFq2DlHeidYVJnEHWO6pyg33QogxbZvYMCz WtIg== X-Gm-Message-State: AGRZ1gJ8EnBlM7T35G3mrflhZS3e6xjSxN6KeTd6kJpRfDaNt+p9GMCn j36yWOe5ZOFqYINwcYlR5hrGm8FH X-Google-Smtp-Source: AJdET5dBs8kCpGUVh0COW1f61FI6GyZgT4mMPesioWz96FaVqeWB/FMHUvQNF55jpnN1d9qmfCniqg== X-Received: by 2002:ac8:6bc5:: with SMTP id b5mr16358120qtt.182.1541454996412; Mon, 05 Nov 2018 13:56:36 -0800 (PST) X-Google-Original-From: Great Big Dot User-agent: mu4e 1.0; emacs 26.1 Machine: x86_64 OS: linux-gnu Compiler: gcc X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::833 X-BeenThere: bug-bash@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Bug reports for the GNU Bourne Again SHell List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Xref: csiph.com gnu.bash.bug:14765 uname output: Linux ArchBox0 4.18.16-arch1-1-ARCH #1 SMP PREEMPT Sat Oct 20 22:06:45 UTC 2018 x86_64 GNU/Linux Machine Type: x86_64-unknown-linux-gnu Bash Version: 4.4 Patch Level: 23 Release Status: release --text follows this line-- Description: The parameter expansion "${!var[@]}" expands to the indices of an array (whether linear or associative). The expansion "${var-string}" returns "${var}" iff var is set and 'string' otherwise. These two features do not play well together: $ declare -a -- array=([0]=hello [1]=world) $ printf -- '%s\n\n' "${!array[@]-Warning: unset}" bash: hello world: bad substitution $ declare -a -- array=([0]='helloworld') $ printf -- '%s\n\n' "${!array[@]-Warning: unset}" Warning: unset $ declare -a -- array=([0]='hello world') $ printf -- '%s\n\n' "${!array[@]-Warning: unset}" bash: hello world: bad substitution $ declare -a -- array=() $ printf -- '%s\n\n' "${!array[@]-Warning: unset}" Warning: unset As you can see, accessing the index list of multiple-element arrays fails when you append the unset expansion. With single-element arrays, it fails iff the element in question contains any special characters or whitespace, and thinks the array is unset otherwise. (Further testing shows that a value of the empty string also throws an error.) Finally, empty arrays are also considered unset. (This is the one thing that is consistent with the rest of bash, since empty arrays themselves are also considered unset by this expansion; that is, "${array[@]-unset}" yields 'unset' when array isn't set.) This pattern of behavior is apparently unaffected by changes to IFS, using a normal variable as a one-element array, using an unset variable as a zero-element array, or using an associative instead of linear array. That last one has an interesting wrinkle, however: $ declare -A -- assoc=(['k e y']='element') $ printf -- '%s\n\n' "${!assoc[@]-Warning: unset}" Warning: unset $ declare -A -- assoc=(['key']='e l e m e n t') $ printf -- '%s\n\n' "${!assoc[@]-Warning: unset}" bash: e l e m e n t: bad substitution Strangely, whether a single-element array errors (as opposed to giving the wrong result) is only dependent on the the characters in the *element*, not the *key*---despite the fact that only the key's value is being requested! Repeat-By: $ declare -a arr_2_=(zero one); printf '%s\n' "${!arr_2_[@]-unset}" bash: zero one: bad substitution $ declare -a arr_1a=('z e r o'); printf '%s\n' "${!arr_1a[@]-unset}" bash: z e r o: bad substitution $ declare -a arr_1b=('zero'); printf '%s\n; "${!arr_1b[@]-unset}" unset Fix: To avoid this problem, you just need to spend another line or two writing out the relevant conditional explicitly; for example: # ... "${!array[@]-}" if [ -v 'array[@]' ]; then ... "${!array[@]}" ... else ... ... fi Note that `test -v 'array[@]'` has the same "feature" that "${array[@]-default}" does: it treats empty arrays as unset.