1

Good day everyone, I was wondering if you could help me out with a small exercise.

  1. Using the while loop, read the .bashrc file line by line and count the number of the lines in which we do not encounter any numbers.

Basically, it's a script but I can't seem to come up with anything. Any help or suggestion is appreciated. I wanted to know if it's feasible to use grep or awk in this case.

My attempt:

cat .bashrc | while read line; 
do if [ check_if_there_is_no_number_in $line ]; 
then increase_your_index>
fi done

Could anyone help finish the script? Thanks in advance.

Kusalananda
  • 333,661

1 Answers1

2

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.

Kusalananda
  • 333,661