False fails on Bash Word Count tests?

Hi! First of all I’m having a great time!
I think I might have found an unexpected bug in the online testing of this exercise. I’m having no problems on my local machine. Something is going wrong with having apostrophes in my array values.

Anyway, here’s the code:

#!/usr/bin/bash

Main() {
    local Input="$1"
    local -A WordCount
    read -ra Words <<< "${Input//[^a-zA-Z0-9\']/ }"

    for Word in "${Words[@]}"; do
        Word=${Word//[^a-zA-Z0-9\']}
        Word=${Word/#\'/}
        Word=${Word/%\'/}
        Word=${Word,,}
        if [[ $Word != "" ]]; then
        ((++WordCount["$Word"]))
        fi
    done

    for Key in "${!WordCount[@]}"; do
        printf "%s: %d\n" "$Key" "${WordCount[$Key]}"
    done
}

Main "$@"

What’s your local bash version?

Hi Glenn!
It’s recent, 5.2.26.

What is the test runner producing? Are you using bats to test locally?

I am using bats to test locally, that’s correct:

word_count.bats
 ✓ count one word
 ✓ count one of each word
 ✓ multiple occurrences of a word
 ✓ handles cramped lists
 ✓ handles expanded lists
 ✓ ignore punctuation
 ✓ include numbers
 ✓ normalize case
 ✓ with apostrophes
 ✓ with quotations
 ✓ substrings from the beginning
 ✓ multiple spaces not detected as a word
 ✓ alternating word separators are not detected as a word
 ✓ quotation for word with apostrophe
 ✓ contains shell globbing character

15 tests, 0 failures

Edit: I have technically solved the online problem by replacing the apostrophes with an underscore and afterwards switching them back. Hacky, but it works.

This is a bug that got fixed in 5.2. Unfortunately, at the moment, the online test runner is on 5.1.

If you add shopt -s assoc_expand_once, you’ll pass the tests online.

This is bash 5.2

$ declare -p BASH_VERSION
declare -- BASH_VERSION="5.2.26(1)-release"
$ var="don't"
$ declare -A words
$ words["$var"]=0
$ (( words["$var"] += 1 ))
$ declare -p words
declare -A words=(["don't"]="1" )

This is bash 5.1

$ declare -p BASH_VERSION
declare -- BASH_VERSION="5.1.0(1)-release"
$ var="don't"
$ declare -A words
$ words["$var"]=0
$ (( words["$var"] += 1 ))
bash: ((: words[don't] += 1 : bad array subscript (error token is "words[don't] += 1 ")
$ shopt -s assoc_expand_once
$ (( words["$var"] += 1 ))
$ declare -p words
declare -A words=(["don't"]="1" )

Tons of details at https://unix.stackexchange.com/questions/627474/how-to-use-associative-arrays-safely-inside-arithmetic-expressions

And I’ve got some commentary on my answer: https://exercism.org/tracks/bash/exercises/word-count/solutions/glennj

1 Like

The test-runner is on an older Ubuntu with the older bash. Maybe I’ll see about using Alpine instead.

Thanks for the added context Glenn, it’s appreciated! Haven’t really used the shopt builtin much either, seems it could have saved me several other past headaches. This was driving me up the wall hahaha.

If you look at my solution, you may notice there are 18 iterations…

1 Like

You probably know this, but Alpine doesn’t use the GNU utils (or systemd but that aside). It might come with other unexpected results.

Hahaha oh god I feel the pain.

The bash track focuses on bash and not other utils. I would be fine without most the GNU utils. I think bc is the only one that really gets used (for floating point math).

While I certainly feel like that should be the case, a large portion of the community answers often use more than just bash and bc. gawk, grep and tr are ones I see often.

and sed.

The jq track uses alpine, and apk adds a few packages, so that’s not new.

1 Like

Yeah, sed is another one. There is nothing to worry about I suppose!

hmm, ubuntu 24.04 docker image includes bash 5.2. Safer (from a user’s perspectice – in terms of external tools expectations) to upgrade to that instead of moving to Alpine. It ships with mawk, which I’d suggest is good enough – if a user is relying on gnu-specific awk features, then they’re not trying hard enough to solve it in bash.

Swings and roundabouts I guess. Ubuntu is predictable but Alpine is very light and snappy.

That sounds like a british-ism. Not familiar

I would be fine with breaking those, to be honest.