The wc command is counting the words in the output from grep, which includes "for":
> grep shell test.txt for shell_A shell_B shell_C So there really are 4 words.
If you only want to count the occurrences of a particular word in a file, you can use the -c option of grep, e.g.,
grep -c shell test.txt Neither of those actually count words, but could match other things which include that string. Some implementations of grep provide a -w option for words, however that is not in POSIX. You could use a regular expression with grep to match words (separated by blanks, etc), but your example has none which are just "shell": they all have some other character touching the matches.
For reference: