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

I have a simple question that I can't seem to find the answer to. I want to do a translate using user defined variables. This is what I mean:

$a = "abc"; $b = "def"; $c = "abc leppard"; $c ~= tr/$a/$b/;
Why doesn't this work? I know that the use of $a and $b is frowned upon. What is the 'right' way to do this? I originally thought I could do something like "{$a}", but that doesn't seem to work either. Any tips? -Paul

Replies are listed 'Best First'.
(tye)Re: Variables in Regular Expressions?
by tye (Sage) on Apr 25, 2001 at 23:49 UTC

    tr/// does not use regular expressions so your title has thrown everyone off.

    tr/// only handles compile-time values so you have to use eval to get tr/// to deal with variable data.

    If you are going to use the tr/// more than once, then for efficiency, you should do something like:

    sub generateTr { my( $from, $to )= @_; my $sub= eval <<END; sub { my( \$copy )= \@_; \$copy =~ tr/\Q$from\E/\Q$to\E/; return \$copy; } END die "$@" if $@; return $sub; } my $xlate= generateTr( "abc", "def" ); my $c= $xlate->( "abc leppard" ); # $c is now "def leppdrd"

            - tye (but my friends call me "Tye")
Re: Variables in Regular Expressions?
by busunsl (Vicar) on Apr 25, 2001 at 23:36 UTC
    There are several faults here:
    ~= should probably be =~
    tr does a translation from one character to another and has nothing to do with regular expressions.
    This should probably be s/...


    $a = "abc"; $b = "def"; $c = "abc leppard"; $c =~ s/$a/$b/;
      I was trying to come up with an interesting example but failed. I actually _do_ want to do translation. (I'm writing a little crytpogram helper tool.) I want to replace all the letters from an alphabet, say $a, with all the letters from the new alphabet, say $b.
      # the alphabet $a = "abcdefghijklmnopqurtuvwxyz"; # i've discovered that a represents T in the cryptogram, for example $b = "T E "; $c = "the text i want to decipher"; $c =~ tr/$a/$b/;
      So basically, is there any way to get this to work? Thanks for your help.
        Ok, here it is:

        Right from the perlop manpage:

        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 $@;
        Do a perldoc perlop to read all about tr
Re: Variables in Regular Expressions?
by damian1301 (Curate) on Apr 25, 2001 at 23:37 UTC
    This is what I used, and yes it does work.

    #!/usr/bin/perl $a = "abc"; $b = "def"; $c = "abc leppard"; $c =~ s/$a/$b/; print $c;

    I didn't think you could transliterate on that so I tried it and then tried a substitution. To my avail, it worked.
    Just so all these other monks that think a transliteration will work, this is what I got when I ran it as  tr/$a/$b/;

    bbc leppbrd
    Which, I doubt is what he wanted.

    PS: May I ask what ~= is? I think you mean =~. :)

    UPDATE: It seems that everyone likes to answer this in a minute's time. Chady and some other monk already beat me to it :)

    Tiptoeing up to a Perl hacker.
    Dave AKA damian

Re: Variables in Regular Expressions?
by KM (Priest) on Apr 25, 2001 at 23:39 UTC
    Why are you using tr at all? This is likely best done with s///

    $c =~ s!$a!$b!;


Re: Variables in Regular Expressions?
by Chady (Priest) on Apr 25, 2001 at 23:36 UTC

    try :

    $c =~ tr/$a/$b/;
    Update: below posts answer better, use s/// instead

    He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.

    Chady | http://chady.net/
Re: Variables in Regular Expressions?
by Anonymous Monk on Apr 25, 2001 at 23:39 UTC
    Your code has a transposed substitution operator (should be =~ not ~=). I don't recall 'tr' options off the top of my head, but a substitution like this will work fine:
    $c =~ s/$a/$b/;
Re: Variables in Regular Expressions?
by suaveant (Parson) on Apr 25, 2001 at 23:37 UTC

    Update oops, read it wrong... and other people have answered it.
                    - Ant

Re: Variables in Regular Expressions?
by suaveant (Parson) on Apr 25, 2001 at 23:42 UTC
    I guess the real question is are you trying to trade a for d, b for e, and c for f, or are you trying to replace abc with def... if it is the first case, you problem was simply the ~= should be =~, if the latter, than you want the s/// solution proposed above
                    - Ant