Bash: Recovering from the word-count exercise

I have finally – with much help from my son and mentor, Bela – struggled through this word-count exercise
I agree that the concept and structure for the exercise is ‘easy’, but I can’t see how its Bash implementation got so labeled. Actually, I’m even in disagreement conceptually. For this implementation the string ‘a,b,c’ is 3 words: in my first attempt it was one word: ‘abc’. And when I run it through the wc command it, too, reports one word. But that’s a matter of taste, and I redid it to get 3 words.
But getting it to increment correctly for words containing an apostrophe was so tricky that one of our resident experts here, glennj, details in his solution the various sources he consulted to come to something that works. And one of the tests presented ‘\n’ as ordinary text but expects an answer that interprets it as a return, so you essentially have to fake your way through it (My son/mentor reported that the other day, and it was instantly fixed, probably by glennj). Anyway, I don’t think that this exercise is ‘easy’ in Bash.

Thanks for the feedback. It’s very valuable to hear students’ actual experiences.

I can’t comment on your code without seeing it, but as you’ve read my solution and the steps I had to go through, I do agree that bash does not make this one easy.

The code was complicated by a series of bugs in bash releases. She was initially trying to do:

    typeset -A wordcount  # an associative array
...
    (( wordcount["$word"]+= 1 ))

– and this worked fine for most $word values, but not ones with an apostrophe, like "don't".

It turns out that some bash versions mistakenly require the expanded string to meet arithmetic evaluation context parsing rules; others don’t. And crucially, the shell she was using on her machine worked one way; the shell used by Exercism’s online test suite when she tried to submit the exercise worked the other way.

I surveyed a bunch of bash shells I had laying around on different machines, and there was all sorts of crazy variance. Like:

  • 2.03.0 – fails (I think this is before associative arrays were added)
  • 3.1.11 – works
  • 3.2.57 – fails (Mac OS /bin/bash, apparently built without associative array support)
  • 4.3.11 – works
  • 4.3.30 – works
  • 5.0.17 – fails
  • 5.2.15 – works

And then the workaround I came up with also worked on only a subset:

    : $(( wordcount["$word"]+= 1 ))

– I didn’t survey, but it worked on a different subset of versions. The final code has a very clear, lumpy workaround:

       tmp=${wordcount["$word"]}
       ((tmp++))
       wordcount["$word"]=$tmp

Anyway, the need to struggle through a morass of bash bugs didn’t help the exercise be ‘easy’ :)

1 Like

Screenshot excerpt of my own last comment: to illustrate somewhat / somehow, what bash itself was up against and what the student was consequentially up against.

Both of the code snippets here were quoted with ```bash … ```. Observe how the forum’s bash syntax highlighter has highlighted wordcount["$word"] in three different ways. The first one has only $word in blue; the 2nd has the entire ${wordcount["$word"]} parameter expansion in blue; and the 3rd is almost the same as the 1st, except now the quotes are suddenly in red!

Because this is an ugly and nebulous language to parse :)

tmp

Well, a syntax highlighter is usually a mess of regular expressions. It’s certainly not how bash parses code.

“an ugly and nebulous language” – no argument!

1 Like