in reply to tr/// statement

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 }

Replies are listed 'Best First'.
A another tr/// statement question..
by supernewbie (Beadle) on Jul 19, 2001 at 16:03 UTC
    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

      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

        Muchas gracias Kevin!

      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

      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 $! ...)

      Regards... Stefan

        Thank you very much Stefan!
      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";
Re: Re: tr/// statement
by supernewbie (Beadle) on Jul 19, 2001 at 13:14 UTC
    Thanks for your help! Appreciated!!