in reply to Using variables with tr///

Also from perlop:
Note that because the transliteration table is built at compile time, neither the SEARCHLIST nor the REPLACEMENTLIST are subjected to double quote interpolation. That means that if you want to use variables, you must use an eval(): eval "tr/$oldlist/$newlist/"; die $@ if $@; eval "tr/$oldlist/$newlist/, 1" or die $@;

Replies are listed 'Best First'.
RE: Re: Using variables with tr///
by DrManhattan (Chaplain) on Jul 17, 2000 at 19:59 UTC

    This is significantly faster than using eval:

    sub count { my ($string, $char) = @_; my $index = -1; my $count = -1; do { $count++; $index = index($string, $char, $index + 1); } while ($index != -1); return $count; }

    And this is faster still:

    sub count { my ($string, $char) = @_; $string =~ s/[^$char]//g; return length($string); }
    Eval: 56 wallclock secs (45.19 usr + 0.00 sys = 45.19 CPU) @ +3319.32/s (n=150000) While Loop: 5 wallclock secs ( 4.69 usr + 0.00 sys = 4.69 CPU) @ +31982.94/s (n=150000) Substitution: 1 wallclock secs ( 1.41 usr + 0.00 sys = 1.41 CPU) @ +106382.98/s (n=150000)

    Update (7/19/00): Oh, duh. s/// returns a count of the number of changes made. Here's a faster way to write the subroutine:

    sub count { my ($string, $char) = @_; return ($string =~ s/$char//g); }

    - Matt

RE: Re: Using variables with tr///
by greenhorn (Sexton) on Jul 17, 2000 at 12:05 UTC
    It does sound as if s/// might end up being as efficient (perhaps unless the string is quite long...subject for further tests). Now I see that the question stems in part from an RTFM problem, shame on me. Perhaps I will vote against my own message. Thanks, plaid and btrott.

Re: Re: Using variables with tr///
by frankus (Priest) on Nov 14, 2001 at 21:24 UTC
    This also means by implication that $_ must be used:
    eval("$c= $d =~ tr/$e/$f/")
    Opens a whole bag of bunnies, I think you'll agree.
    I've had to use:  eval "tr/$a/$b/" instead.


    Brother Frankus.