Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

Re: How to use a variable in tr///

by inman (Curate)
on Apr 08, 2005 at 08:43 UTC ( #445976=note: print w/replies, xml ) Need Help??

in reply to How to use a variable in tr///

From the documentation:

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 $@; # or eval "tr/$oldlist/$newlist/, 1" or die $@;

Replies are listed 'Best First'.
Re^2: How to use a variable in tr///
by Roy Johnson (Monsignor) on Apr 08, 2005 at 13:27 UTC
    As merlyn points out, that's not delimiter safe. However, it can be made safe with quotemeta:
    eval sprintf "tr/%s/%s/", map quotemeta, $oldlist, $newlist;
    Update: of course nobull's construction below is much clearer. It should have occurred to me to say
    eval "tr/\Q$oldlist\E/\Q$newlist\E/";

    Caution: Contents may have been coded under pressure.
      This is great, but I was confused for a while and tinkered with it. Here's an annotated version:
      #! /usr/bin/perl -w use strict; my $fname = "aaabbbcccddd"; # Some creepy / characters to prove the quotemeta is doing its job my $orig = "abc/"; my $repl = "def/"; print "before: $fname\n"; $_ = $fname; eval sprintf "tr/%s/%s/", map quotemeta, $orig, $repl; $fname = $_; print "after: $fname\n"; =for explain The eval line above was confusing to me at first (and I'm not even a total newbie). It may help to see it delimited with more parenthesis: eval (sprintf ("tr/%s/%s/", map (quotemeta, $orig, $repl))); From right to left: The map uses quotemeta as its EXPR and $orig, $repl as its input list quotemeta is operating on a local $_ The two variables sprintf is expecting are in the list output from map eval is evaluating the resulting string made by sprintf. The tr/// is operating on $_ =cut
      I think I'd probably want to precompile too if this was to be used repeatedly.
      my $tr = eval "sub { tr/\Q$oldlist\E/\Q$newlist\E/ }" or die $@; &$tr for $things, $that, $i, $want, $to, $transliterate;

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://445976]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (4)
As of 2021-04-13 10:18 GMT
Find Nodes?
    Voting Booth?

    No recent polls found