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";
| [reply] [d/l] [select] |
|
|
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; | [reply] [d/l] [select] |
|
|
| [reply] |
|
|
|
|
|
|
#!/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. | [reply] [d/l] [select] |
|
|
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.
| [reply] [d/l] [select] |
|
|
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? | [reply] [d/l] [select] |
|
|
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?
| [reply] |
|
|
$in =~ tr/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456
+789!@#$%^&*:?_+\-=|'";.,\/ /Tj\-Gns1Nmp8Qc3Y6L_v&^iyeDalX2RMHPr+w4%x!
+zWgf;0U.KZ\/oFVk@ dJtEb$'=*#IAB:,9S5"Oqh7|?uC/;
| [reply] [d/l] |
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.
| [reply] [d/l] |
Re: doing tr/// on-the-fly?
by ambrus (Abbot) on Mar 19, 2010 at 13:54 UTC
|
| [reply] |