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

I didn't understand why the results would be different when printing out $string1 and $string2 in below script. I thought the 'tr' operator would work the same way on both strings. Please help! The result from printing $string1: "b b b." The result from printing $string2: " ."

#!/usr/bin/perl $string1 = 'the cat sat on the mat.'; $string1 =~ tr/a-z/b/d; print "$string1\n"; $string2 = 'the cit sit on the mit.'; $string2 =~ tr/a-z/b/d; print "$string2\n";

Replies are listed 'Best First'.
Re: transliterate on regex
by CountZero (Bishop) on Jun 19, 2013 at 06:07 UTC
    From the docs:
    If the /d modifier is used, the REPLACEMENTLIST is always interpreted exactly as specified. Otherwise, if the REPLACEMENTLIST is shorter than the SEARCHLIST, the final character is replicated till it is long enough.

    tr/a-z/b/d therefore means: replace 'a' by 'b' and all other lowercase alpha-chars by nothing; leave everything else as it is. Hence you end up in your second example with 5 spaces and a full stop.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
Re: transliterate on regex
by Anonymous Monk on Jun 19, 2013 at 04:42 UTC
    See tr/// and consider
    $_ = '1 the cat sat on the mat.'; tr/abcdefghijklmnopqrstuvwxyz0-9/aBCDEFGHIJKLMNOPQRSTUVWXYZ/d; print "$_\n"; $_ = '2 the cit sit on the mit.'; tr/abcdefghijklmnopqrstuvwxyz0-9/ABCDEFGHiJKLMNOPQRSTUVWXYZ/d; print "$_\n"; __END__ THE CaT SaT ON THE MaT. THE CiT SiT ON THE MiT.

    Do you get it now?

    tr/searchlist0123456789 /REPLACEMENTLIST/d
      Excellent example; but consider use of a character class (see perlre rather than specifying all 52 lc & uc letters from a to z and the 10 digits from 0 to 9...
      [a-zA-Z0-9]
      C:\>perl -E "my $s='abcdeEFGHI20130619ABC';$s =~ tr/[b-dB-D2-5]/*/;say + $s;" a***eEFGHI*01*0619A**

      update: restating for specificity: 52 uc and lc; 10 digits

      update2: choroba points out that (s)quare brackets are not special in tr///; ie, that my suggestion of a char class is wrong -- something illustrated by this:

      C:\>perl -E "my $s='abcdeEFGHI20130619ABC';$s =~ tr/b-dB-D2-5/*/;say $ +s;" a***eEFGHI*01*0619A**

      Mea Culpa.


      If you didn't program your executable by toggling in binary, it wasn't really programming!

        Try adding [] into $s...
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Got it - thanks.