3

This code in Bash

s="There are seven pencil"
declare -A A
while IFS= read -rn1 a; do
 [ -z "$a" ] || [ -n "${A[$a]}" ] && continue
 printf %s "$a"
 ((A[$a]++))    # A[$a]=x
done <<<"$s"
echo

produces this line

Ther a svn pcil

All spaces printed out. Is this behaviour documented or in any other way expected?

Still, when ((A[$a]++)) is replaced with A[$a]=x, the output changes to

Ther asvnpcil

So this time only the first space is printed.

What's the difference?

This is in GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu).


There's a third operation to compare to, namely let "A[$a]=x". Strangely, it falls somewhere in between the former two. It produces the line with all spaces, ie. Ther a svn pcil. But using the reduction from isaac's answer, it behaves like the A[$a]=x assignment:

$ unset A; declare -A A; let "A[' ']++"; declare -p A
declare -A A=([" "]="1" )

Eventually, I've sent a bug report with this. Here's its thread.

2

The core issue is in using arithmetic to declare a variable.

Replace:

(( A[$a]++ ))

with

declare -A A["$a"]=1

And the repeated spaces are removed.


It seems to me to be a bug, an space fails to create the variable:

$ declare -A A; (( A[" "]++ )); declare -p A
declare -A A

Addressing your edit after I posted the above answer:

What's the difference?

That an assignment does declare the variable as part of the array:

$ unset A; declare -A A; A[" "]=1 ; declare -p A
declare -A A=([" "]="1" )

while an arithmetic expansion fails to do the equivalent:

$ unset A; declare -A A; (( A[" "]=1 )); declare -p A
declare -A A
| improve this answer | |
  • I agree with the difference, and I agree that it looks like a bug. I have one more reference: declare -A A; let "A[' ']++"; declare -p A gives declare -A A=([" "]="1" ). – user147505 Jan 25 '18 at 1:39
  • I have doubts about the syntax in this line of your answer: declare -A A["$a"]=1. It looks to me like declaring another associative array. Simple declare A["$a"]=1 makes the change too. – user147505 Jan 25 '18 at 1:48
  • @tomasz Both syntaxes are valid and equivalent. No it is not declaring a new variable, the name is still A for both declarations. – Isaac Jan 25 '18 at 1:51
  • Strangely, let "A[$a]=x" produces all spaces in the original context. (I updated my question.) – user147505 Jan 25 '18 at 2:05
  • 1
    Testing with unset A; a=" ";declare -A A; let "A[$a]=x"; declare -p A still fails to create the variable, thus all spaces is the expected result. @tomasz – Isaac Jan 25 '18 at 2:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy