Yes, it's feasible to use grep
to do this task:
grep -c -v '[[:digit:]]' ~/.bashrc
This would read you ~/.bashrc
file, line by line. If any line contains a digit (assuming this is enough to detect "a number"), it will be discarded. The rest of the lines will be counted and the total number of lines not containing any digit will be displayed.
See man grep
for a description of the -c
and -v
options, but basically, -c
makes grep
return the number of matching lines (instead of the lines themselves) and -v
inverts the sense of the match so that only lines not matching the given pattern are returned.
The pattern [[:digit:]]
would match on any line containing a digit.
With awk
, you'd have to keep track of the number of lines yourself:
awk '!/[[:digit:]]/ { count++ } END { print count }' ~/.bashrc
Here, the !
in front of the test for a digit on the current line inverts the sense of the test. If the test succeeds for a line, the variable count
is incremented. The END
block is executed when there are no further lines to read and will output the current value of count
.
An improvement to this script would be necessary if we expect to encounter files where there are no lines without digits, as count
would be empty (not 0
). This could be done with a BEGIN { count = 0 }
block, or by forcing an arithmetic evaluation in the print
statement with print 0+count
, for example.
Assuming you have read and understood "Why is using a shell loop to process text considered bad practice?" and "Understanding "IFS= read -r line"", we may, for the purpose of satisfying a teacher's specifications, use a /bin/sh
script:
#!/bin/sh
count=0
while IFS= read -r line; do
case $line in
*[[:digit:]]*)
;;
*)
count=$(( count + 1 ))
esac
done < ~/.bashrc
printf 'There are %d lines with no digit\n' "$count"
or, with bash
,
#!/bin/bash
count=0
while IFS= read -r line; do
[[ $line != *[[:digit:]]* ]] && count=$(( count + 1 ))
done < ~/.bashrc
printf 'There are %d lines with no digit\n' "$count"
While the grep
and awk
solutions use regular expression matches, the two loops shown here both use "globbing patterns" to match digits.
Personally, I'd go for the simpler grep
solution. I would never "ok" the above while
loops in production code, on account of being unnecessary when grep
has the same functionality built in. Also, I had to correct about two typos and omissions while writing them, which means that a sloppier programmer would potentially make more mistakes, which probably wouldn't be the case with the simple grep
solution.