# Count occurences of a numeric string falling in a range

**URL:** <https://community.unix.com/t/count-occurences-of-a-numeric-string-falling-in-a-range/290711>\
**Category:** Shell Programming and Scripting\
**Created:** [June 30, 2011, 1:54am UTC](https://community.unix.com/t/count-occurences-of-a-numeric-string-falling-in-a-range/290711 "2011-06-30T01:54:19Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![chen.xiao.po](https://community.unix.com/letter_avatar/chen.xiao.po/32/5_5575768a8748004e209b776fc1b2916d.png) [@chen.xiao.po](https://community.unix.com/u/chen.xiao.po)\
**Post date:** [June 30, 2011, 1:54am UTC](https://community.unix.com/t/count-occurences-of-a-numeric-string-falling-in-a-range/290711/1 "2011-06-30T01:54:19Z")

</div>

Dear all,

I have numerous dat files (1.dat, 2.dat...) containing 500 numeric values each. I would like to count them, based on their range and obtain a histogram or a counter.

INPUT:

1.dat  
1.3  
2.16  
0.34  
......

2.dat  
1.54  
0.94  
3.13  
.....

3.dat  
2.34  
4.12  
2.7  
.....

OUTPUT:  
example-  
1.dat: low (2\>) - 200 ; medium (3\> and 2\<) - 50 ; high (3\<) -250

(the output can be in any comprehensive format)

I used the following script, in vain!

Code:

#!/bin/csh  
set k = 1  
while ($k = 250)

set i=0  
set low = 0  
set medium = 0  
set high = 0  
foreach line ("`cat $k.dat`")  
set j = `printf $line`  
if ($j \< 2) then  
@low = $low +1  
else if ($j \> 2 and \<3) then  
@medium = $medium +1  
else if ($j \> 3) then  
@high = $high +1  
else  
endif  
end

echo "$k - $low $medium $high"  
@k = $k +1  
end

I get an error sayin "if: Badly formed number.  
Could you please help?

Thanks,  
Po

---

<div class="post-metadata">

**Author:** ![bartus11](https://community.unix.com/user_avatar/community.unix.com/bartus11/32/1418_2.png) [@bartus11](https://community.unix.com/u/bartus11)\
**Post date:** [June 30, 2011, 3:25am UTC](https://community.unix.com/t/count-occurences-of-a-numeric-string-falling-in-a-range/290711/2 "2011-06-30T03:25:08Z")

</div>

Place this script in the directory containing .dat files, then run it there.

```nohighlight
#!/usr/bin/perl
chomp(@files=`ls *.dat`);
for $i (@files){
  open I, "$i";
  $l=$m=$h=0;
  while ($n=<I>){
    chomp $n;
    $l++ if $n<=2;
    $m++ if $n>2 && $n<=3;
    $h++ if $n>3;
  } 
  print "$i: low (2>) - $l ; medium (3> and 2<) - $m ; high (3<) - $h\n";
}

```

---

<div class="post-metadata">

**Author:** ![chen.xiao.po](https://community.unix.com/letter_avatar/chen.xiao.po/32/5_5575768a8748004e209b776fc1b2916d.png) [@chen.xiao.po](https://community.unix.com/u/chen.xiao.po)\
**Post date:** [June 30, 2011, 3:36am UTC](https://community.unix.com/t/count-occurences-of-a-numeric-string-falling-in-a-range/290711/3 "2011-06-30T03:36:30Z")

</div>

Thanks Bartus11  
:b:

---

<div class="post-metadata">

**Author:** ![birei](https://community.unix.com/letter_avatar/birei/32/5_5575768a8748004e209b776fc1b2916d.png) [@birei](https://community.unix.com/u/birei)\
**Post date:** [June 30, 2011, 4:02am UTC](https://community.unix.com/t/count-occurences-of-a-numeric-string-falling-in-a-range/290711/4 "2011-06-30T04:02:49Z")

</div>

Hi,

Other solution using 'perl' too:

```nohighlight
$ cat script.pl
use warnings;
use strict;

die "Usage: perl $0 low-range medium-range high-range files\n" unless 
    @ARGV >= 4 and
    grep { /^-?\d+$/ } @ARGV[0..2] and # Integer ranges.
    defined $ARGV[3]; # At least one file.

my %range = (
    low_limit => shift,
    medium_limit => shift,
    high_limit => shift
);

while ( <> ) {
    ## Only count lines without number.
    if ( /^\s*\d+(?:\.\d*)\s*$/ ) {
        if ( $_ < $range{ low_limit } ) {
            $range{ low_num }++;    
        } elsif ( $_ >= $range{ low_limit } && $_ < $range{ medium_limit } ) {
            $range { medium_num }++;
        } elsif ( $_ >= $range{ high_limit } ) {
            $range{ high_num }++;
        }
    }

    ## Print result in end of each file.
    if ( eof ) {
        printf 
            "%s: low (%d<) - %d ; medium (>%d and %d<) - %d ; high (>%d) - %d\n", 
            $ARGV,
            $range{ low_limit },
            $range{ low_num } || 0,
            $range{ low_limit },
            $range{ medium_limit },
            $range{ medium_num } || 0,
            $range{ high_limit },
            $range{ high_num } || 0,
            delete @range{ qw(low_num medium_num high_num) }; 
    }
}
$ perl script.pl
Usage: perl script.pl low-range medium-range high-range files
$ perl script.pl 2 3 3 *.dat # Output with my test files.
1.dat: low (2<) - 4 ; medium (>2 and 3<) - 1 ; high (>3) - 1
2.dat: low (2<) - 2 ; medium (>2 and 3<) - 1 ; high (>3) - 3

```

Regards,  
Birei
