0

I have several files with the following content:

GGHTERR_01218   GGHTERR_02418   GGHTERR_01991
GGHTERR_02211   GGHTERR_02297   GGHTERR_02379
GGHTERR_02294   GGHTERR_02455   GGHTERR_02374
GGHTERR_00532   GGHTERR_00534
GGHTERR_00533   GGHTERR_00535
GGHTERR_00776   GGHTERR_00779
GGHTERR_01220   GGHTERR_01620
GGHTERR_01760   GGHTERR_01761
GGHTERR_01774   GGHTERR_02404
GGHTERR_01889   GGHTERR_01890
GGHTERR_02081   GGHTERR_02287
GGHTERR_02152   GGHTERR_02153
GGHTERR_02260   GGHTERR_02321
GGHTERR_02295   GGHTERR_02375
GGHTERR_02419   GGHTERR_02437
GGHTERR_02420   GGHTERR_02438
GGHTERR_02430   GGHTERR_02448
GGHTERR_00001
GGHTERR_00002
GGHTERR_00003
GGHTERR_00004
GGHTERR_00005
GGHTERR_00006
GGHTERR_00007

I would like to know if there is an easy way to count the number of rows that have 3 columns, 2 columns and 1 column.

So the output should look like:

3 columns: 3
2 columns: 14
1 colums: 7
0

2 Answers 2

8

Awk is perfect for this. It will split lines at whitespace (by default; change with the -F option) and the internal variable NF (number of fields) has the number of fields per line. So, just go through the file, saving the NF for each line:

awk '{ 
        nums[NF]++
     }
     END{
        for(num in nums){
            printf "%d columns: %d\n", num, nums[num]
        }
     }' file

The code above just stores the number of fields (NF) in the associative array nums whose keys are the number of fields and values are the number of times that number of columns was found in the file. At the end, we just go through the array and print. Running the above on your example results in:

$ awk '{ nums[NF]++}END{for(num in nums){printf "%d columns: %d\n", num, nums[num]}}' file
1 columns: 7
2 columns: 14
3 columns: 3

One (small) drawback of this approach is that you will need to keep an entry for each line in the file in memory. That won't be a problem unless your file is absolutely gigantic or you have extremely little memory available, but if it is, you can get around it by just printing out the number of fields per line and then counting:

$ awk '{ print NF}' file | sort | uniq -c
      7 1
     14 2
      3 3

Or, to get the same output:

$ awk '{ print NF}' file | sort | uniq -c | while read num fields; do printf "%d columns: %d\n" "$num" "$fields"; done
7 columns: 1
14 columns: 2
3 columns: 3
0

A non awk solution, a little cumbersome maybe:

$ a=$(grep '^[GHTER_0-9]\+[[:space:]]\+[GHTER_0-9]\+[[:space:]]\+[GHTER_0-9]\+$' file | wc -l)
$ b=$(grep '^[GHTER_0-9]\+[[:space:]]\+[GHTER_0-9]\+$' file | wc -l)
$ c=$(grep '^[GHTER_0-9]\+$' file | wc -l)
$ printf "3 columns %s\n2 columns %s\n1 column %s\n" $a $b $c
3 columns 3
2 columns 14
1 columns 7

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .