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
  • 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" ). – Tomasz 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. – Tomasz 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.) – Tomasz 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

Not the answer you're looking for? Browse other questions tagged or ask your own question.