Bash command to check number of words in a file that contain letter “a”
-
3I will not post homework questions on Unix&Linux – Fabby Aug 1 '15 at 19:14
Suppose that we have this test file:
$ cat file
the cat in the hat
the quick brown dog
jack splat
With grep
implementations that have adopted GNU's -o
extension, we can retrieve all the words containing a
:
$ grep -wo '[[:alnum:]]*a[[:alnum:]]*' file
cat
hat
jack
splat
We can count those words:
$ grep -wo '[[:alnum:]]*a[[:alnum:]]*' file | wc -l
4
-
1Personally I would consider using
grep -c
and would also use [aA] or the -i flag to ensure that words with an upper case A are also counted. – Steve Barnes Aug 2 '15 at 14:25 -
Adding
-i
for case-insensitivity is a good idea.-c
counts the number of matching lines of input, not matching words in the output. For example, with the input file above,grep -woc '[[:alnum:]]*a[[:alnum:]]*' file
returns2
because there are two matching lines. By contrast,grep -wo '[[:alnum:]]*a[[:alnum:]]*' file | grep -c .
would give the correct answer. Alternatively, @yaegashi's approach shows a good use ofgrep -c
. – John1024 Aug 2 '15 at 19:49
POSIXly:
<file tr -s '[:space:]' '[\n*]' | grep -c a
Here, words are sequences of non-spacing characters.
Here's a Perl way:
perl -0lnE 'say scalar grep(/a/,split(/\s/,$_));' file
And an awk
way:
awk '{for(i=1;i<=NF;i++){if($(i)~/a/){k++}}}END{print k}' file
-
1Won't that just give you the number of a's in the file rather than the number of words containing a? – Colin 't Hart Aug 1 '15 at 19:01
-
@Colin'tHart um. Yes. Indeed it will. Thanks, no idea what I was thinking there. – terdon♦ Aug 1 '15 at 19:24
awk 'BEGIN{RS="[[:space:][:punct:]]"; c=0}
index($0,"a"){c++}
END{print c}'
Using a version of awk
that supports multi-character Record Separator (RS
), eg. GNU awk, you can cause awk
to read one word per record.
Within that record, the index(in, string)
function searches in
for the first occurrence of string
, and returns the 1-based character position of where it is found. If not found, index()
returns 0. Thus the return value can be treated as a boolean condition test (0 = false, not zero = true). Note, this is not a regular expression search.
If a match is found, the variable c
is incremented by 1 (c++
)
The c=0
is required in the BEGIN{}
block, for when c
is never incremented - which would cause c
to be null
instead of 0
. Another way to handle this issue would be to print 0+c
(in the END{}
block)
-
2This relies on a version of awk that supports multi-character
RS
(e.g. GNU awk). I would probably put a+
at the end of the pattern[[:space:][:punct:]]+
to match one or more characters and just use/a/{c++}
(although I guessindex
might be marginally quicker). Some explanation would make your answer more useful. – Tom Fenech Aug 1 '15 at 14:55