Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm not getting it, and I have two questions.

Thanks for any help you can provide.

Replies are listed 'Best First'.
Re: doing tr/// on-the-fly?
by jwkrahn (Abbot) on Mar 18, 2010 at 01:16 UTC

    First off, tr/// does not do interpolation, strings or regular expressions.    For that you need s///g.

    Your expression my $result = eval "tr/$search/$replace/"; is short for my $result = eval "\$_ =~ tr/$search/$replace/"; but it appears that there is nothing in $_.    Perhaps you meant:

    my $s = 'eabcde'; my $search = 'abcd'; my $replace = 'efgh'; eval "\$s =~ tr/$search/$replace/"; print "$search\n"; print "$replace\n"; print "$s\n";
      Extending this to get the number of substitutions...
      my $result; eval "\$result = \$s =~ tr/$search/$replace/";
      Also, the OP would have gotten warning messages with use warnings;

        Thanks. That is useful information to have.

        Any information on CPAN modules to use for escaping? It would really help if something were installed by default. :)

      Thanks. That helps some.

      Changing the code to the following:

      #!/usr/bin/env perl use strict; my $s = 'eabcde'; my $t = $s; print "$t\n"; $t =~ tr/abcd/efgh/; print "$t\n"; print '*' x 4, $/; my $search = 'abcd'; my $replace = 'efgh'; $t = $s; print "$t\n"; eval { $t =~ tr/$search/$replace/; }; print "$search\n"; print "$replace\n"; print "$t\n";
      Gives me the results:
      eabcde eefghe **** eabcde abcd efgh epbade
      I don't see why the results of tr/// differ.
        eval BLOCK and eval EXPR, despite the similarity in name, are very different functions. You might know the former as try, an exception catching block. The latter also catches exceptions, but its goal is to parse and run dynamically generated Perl code.
        Okay, I didn't duplicate exactly what you said. The following code:
        #!/usr/bin/env perl use strict; my $s = 'eabcde'; my $t = $s; print "$t\n"; $t =~ tr/abcd/efgh/; print "$t\n"; print '*' x 4, $/; my $search = 'abcd'; my $replace = 'efgh'; $t = $s; print "$t\n"; eval "\$t =~ tr/$search/$replace/"; print "$search\n"; print "$replace\n"; print "$t\n";
        ...does give me the expected results:
        eabcde eefghe **** eabcde abcd efgh eefghe
        Why the difference?
Re: doing tr/// on-the-fly?
by toolic (Bishop) on Mar 18, 2010 at 01:47 UTC
    My second question lies in making these strings more complicated -- to the point of containing regular expression metacharacters.
    tr/// does not support regular expressions:
    Note that tr does not do regular expression character classes such as \d or :lower:. The tr operator is not equivalent to the tr(1) utility. If you want to map strings between lower/upper cases, see lc and uc, and in general consider using the s operator if you need regular expressions.
    Obviously I need to escape them,
    If you do end up using s///, you can escape the regular expression using quotemeta.
    Is there a default module which does such escaping, or is there a CPAN module which does what I need?
    Probably. Can you show more small examples of what you are trying to replace?

      Can you show more small examples of what you are trying to replace?

      Sure. Here's one case:

      $in =~ tr/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456 +789!@#$%^&*:?_+\-=|'";.,\/ /Tj\-Gns1Nmp8Qc3Y6L_v&^iyeDalX2RMHPr+w4%x! +zWgf;0U.KZ\/oFVk@ dJtEb$'=*#IAB:,9S5"Oqh7|?uC/;

Re: doing tr/// on-the-fly?
by BrowserUk (Patriarch) on Mar 18, 2010 at 09:32 UTC

    If you need to use a runtime-defined tr/// on more than one line, re-evaling it for each line gets very expensive. It's better to eval a subroutine into existance and use that:

    #! perl -slw use strict; sub makeTR{ return eval "sub{ \$_[ 0 ] =~ tr[$_[0]][$_[1]] }"; } my $myTR = makeTR( 'abcd', '1234' ); for my $str ( qw[ abcd aabbccdd xx axbxcxdx ] ) { my $copy = $str; my $count = $myTR->( $copy ); print "Before: $str After: $copy count: $count"; } __END__ c:\test>junk62 Before: abcd After: 1234 count: 4 Before: aabbccdd After: 11223344 count: 8 Before: xx After: xx count: 0 Before: axbxcxdx After: 1x2x3x4x count: 4

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: doing tr/// on-the-fly?
by ambrus (Abbot) on Mar 19, 2010 at 13:54 UTC