If you want to count the occurrence of each item independantly, and you want to strip the first line off as a header line, and you want the list of items that you're counting to be easily adjustable, this will do the trick.
my $header_line = <DATA>;
my %count;
my @chars = ( qw/F G S/ );
while (my $line = <DATA> ) {
eval "\$count{$_} += \$line =~ tr/$_/$_/,1"
or die $@ foreach @chars;
}
print "There are $count{$_} occurrences of $_\n"
foreach sort keys %count;
__DATA__
Sample header hine
FDIELSIGCOXLSAGICK\n
FDIELSIGCOXLSAGICK\n
The reason that the tr/// must appear inside of an eval block is that variables are not interpolated in tr/// (the transliteration table is built at compiletime, not runtime). Eval forces a fresh compilation of tr/// each time through the loop.
The reason that I pass references is because I want the variables to exist as variables inside the eval, not as values (except in the case of what's inside the tr/// itself).
And the '1' appears at the end of the eval expression so that eval returns safely (without croaking) even if no matches are found.
I think this is an elegant solution, and saves a lot of intricate fiddling.
If you want to see a solution that uses index instead of tr///, you may...
Dave
"If I had my life to do over again, I'd be a plumber." -- Albert Einstein |