Re: tr/// statement
by lestrrat (Deacon) on Jul 19, 2001 at 11:06 UTC
|
I t clearly says on perlop that tr/// does not interpolate, since the search
list is created at compile time. So instead, you would need to do
eval "tr/$var1/$var2/";
if( $@ ) {
## handle error
}
| [reply] [d/l] |
|
|
Could you please give me some more help on this tr/// statement? Could you please tell me if there is any improvement I should do? I use something like this:
@letter = qw( a b c w x y );
for ($n=0; $n<6; $n++){
$x = $letter[$n];
$m = 0;
open (DATA, "data.txt") ||
die "Could not open source data file.";
while (<DATA>) {
$cnt = eval "tr/$x/$x/";
$m += $cnt;
}
print "$x $m";
}
data.txt contains lines like:
aedj dfas jijiojsdf dsfwfy jiox jiohjdfax jojojdjj, oiiia oioje asfdc oujsdfayx soujfosdxjpoiojfdxjljojaois jojojx jopjpx jojoijx joijiodfx
asdfasdf jjalsdf jlajkldf jojiojsd jiojasj ioj wwdn jojae jojocjoc joijss jiojwx jiojoxuiojy joiyu oiuouyy
| [reply] [d/l] |
|
|
This is unrelated to your tr/// problem but I would suggest using:
foreach $x (@letter) {
instead of your for loop, that way you don't have to remember to change the loop termination value from 6 if you change the number of letters.
Kevin O'Rourke
| [reply] [d/l] |
|
|
|
|
I'd rather not open and close the file more than once: disk accesses take time (there's the cache, you didn't mention your file's size). Instead, I would first generate subs that count a given character and store them in a hash, referenced by that character.
Then, for each line in the file, loop over the letters and call the sub from the hash. Increment a counter which is itself stored in a hash.
#!/usr/local/bin/perl
use strict;
my @letter = qw/ a b c x y z /;
my %subs;
my %counts;
foreach ( @letter ) {
$subs{$_} = eval "sub { \$_[0] =~ tr/$_// }";
}
while ( <DATA> ) {
foreach my $letter ( @letter ) {
$counts{$letter} += $subs{$letter}->($_);
}
}
print "$_: $counts{$_}\n" foreach @letter;
__DATA__
aedj dfas jijiojsdf dsfwfy jiox jiohjdfax jojojdjj, oiiia oioje asfdc
+oujsdfayx soujfosdxjpoiojfdxjljojaois jojojx jopjpx jojoijx joijiodfx
asdfasdf jjalsdf jlajkldf jojiojsd jiojasj ioj wwdn jojae jojocjoc joi
+jss jiojwx jiojoxuiojy joiyu oiuouyy
--bwana147 | [reply] [d/l] |
|
|
Hi,
I'd write the whole thing as:
@letter = qw/a b c w x y/;
foreach $x (@letter) {
$m = 0;
open(DATA,"data.txt") or die
"couldn't open data\n$!";
while (<DATA>) {
$m += ($_ =~ s/$x/$x/g);
}
close(DATA);
print "count $x = $m\n";
}
(note the use of foreach, or and $! ...)
| [reply] [d/l] [select] |
|
|
|
|
If you just want letter counts, you could do something like this (though I have a hard time believing this is not homework):
my $letters = "abcwxy";
my $re = qr/[$letters]/;
my $cnt;
while (<INPUT>)
$cnt++ while /$re/g;
}
print "$cnt\n";
| [reply] [d/l] |
|
|
Thanks for your help!
Appreciated!!
| [reply] |
Re: tr/// statement
by Zaxo (Archbishop) on Jul 19, 2001 at 11:09 UTC
|
| [reply] [d/l] [select] |
|
|
| [reply] |