Re: how do I use s///e
by Abigail-II (Bishop) on Jan 26, 2004 at 10:42 UTC
|
s/x/"o" x 5/e is rather inefficient, specially
if you do it in a loop. It's inefficient because you ask Perl
to execute something that always gives the same
result. s/x/ooooo/ or $o = "o" x 4; ...; s/x/$o/ are more efficient.
s///e is interesting if the result of the code in the replacement part depends on the match. s/(\d+)\s*\+\s*(\d+)/$1 + $2/e; for instance.
Abigail | [reply] [d/l] [select] |
Re: how do I use s///e
by borisz (Canon) on Jan 26, 2004 at 10:42 UTC
|
call a subroutine from there. This is very usefull whenever
the replacement is not the same on each iteration.
| [reply] |
|
Agreed. Combining the ability to call a subroute to do your bidding and back references makes for some very handy abilities.
For example:
Say I have a string:
"The %NOUN% can jump very %ADVERB%"
And say I have hash:
%wordBank = (
NOUN => "kangaroo",
ADVERB => "far",
)
I wanted to replace what is in the string with what is in the hash, so originally, I iterated through the hash and did a replace on the string as I found each hash key. This is terribly inefficient, so I reworked it to find items delimited by %..% in the string, and used the delimited keyword to directly call the value from the hash. This save me a lot of time, especially when %wordBank is very large.
#!/usr/bin/perl -w
use strict;
sub safeReplace {
my($hashkey,%hash) = @_;
my $hash = \%hash;
my $retval = '';
if (defined($hash{$hashkey})) {
$retval = $hash{$hashkey};
} else {
$retval = "\%$hashkey\%";
}
return $retval;
}
sub preProcessStr {
my($string,%options) = @_;
$string =~ s/%(.+?)%/safeReplace($1,%options)/ge;
return $string;
}
my %options = (
ARG1 => "test",
ARG2 => "123...",
);
my $string = 'Hello %ARG1%, counting down %ARG2% .. %NOT%';
$string = preProcessStr($string,%options);
print "$string\n"
| [reply] [d/l] [select] |
|
I realize your code was mainly for demonstration purposes, but it can be shortened considerably. I'm sure this can be golfed down even more, but I came up with the following snippet, which I feel is simple yet not too obfuscated (and also demonstrates the use of s///e, so I guess it's not really too OT):
#!/usr/bin/perl
use strict;
use warnings;
my $str = 'The %NOUN% can jump very %ADVERB% with his %APPENDAGES%';
my %wb = (
NOUN => "kangaroo",
ADVERB => "far",
);
$str =~ s/%([^%]+)%/$wb{$1} || "\%$1\%"/ge;
print "$str\n";
Update: %s/\$template/\$str/g; silly mistake caused by last-minute-edits-without-testing. Thanks to Not_a_Number for the catch. | [reply] [d/l] [select] |
|
Re: how do I use s///e
by dominix (Deacon) on Jan 26, 2004 at 10:45 UTC
|
there is a node from BooK that is 59 /e in which there is some demonstration. ;-) but basically look for search and replace in perlretut to have a better understanding.
| [reply] |
Re: how do I use s///e
by Kageneko (Scribe) on Jan 26, 2004 at 17:43 UTC
|
package Filter::ISA;
use strict;
use warnings;
use Filter::Simple;
FILTER_ONLY code => sub {
s/package\s+(\w+?)\s+isa\s+(.+?);/"package $1; use base qw( " . join
+(" ", split(",", $2)) . " );"/eg;
};
1;
Usage:
use Filter::ISA;
package derived isa base1, base2;
| [reply] [d/l] [select] |
Re: how do I use s///e
by halley (Prior) on Jan 26, 2004 at 17:42 UTC
|
If you want to compute the replacements based on the item replaced, s///e is very convenient.
s/(?<!0x)([1-9]\d*)/sprintf "0x%X", $1/eg
I haven't tested this thoroughly, but this should convert any decimal constant in your source into a C/Perl-style hexadecimal constant. It doesn't handle underscores or floating-point well, but it should skip any already-hexadecimal or already-octal numbers.
-- [ e d @ h a l l e y . c c ]
| [reply] [d/l] |
Re: how do I use s///e
by Roy Johnson (Monsignor) on Jan 26, 2004 at 19:47 UTC
|
| [reply] |
Re: how do I use s///e
by inman (Curate) on Jan 26, 2004 at 17:36 UTC
|
In a templating system a substitution of this form can be used to do a lookup on variables being substituted with replacement from a pre-populated hash.
my %myHash = (hello=>"Howdy", goodbye=>"See ya");
while (<DATA>)
{
s/\$(\w+)/$myHash{$1}/eg;
print;
}
__DATA__
When I want to say hello I say $hello.
When I want to say goodbye I say $goodbye!
Update Whoops! Thanks Abigail! This started as an example that used a sub to do the look up in a database but I got all lazy and just did it as a hash. Some revised (incomplete) code below.
s/\$(\w+)/dbLookup($1)/eg;
sub dbLookup {
# Do database lookup (which would take a few more lines!)
return $lookedup ? $lookedup : '';
}
| [reply] [d/l] [select] |
|
There's no point in using /e in your code.
Removing the /e yields the same results.
Abigail
| [reply] |
|
To expand on this, whenever you have a (update: just) variable in the substitution, it's as if you said /e. In a sense, then,
/e just becomes syntactic sugar that you can do away with:
$ echo with bright knives he releaseth my soul | perl -wpe's/(\w+)/${\
+ucfirst($1)}/g'
With Bright Knives He Releaseth My Soul
| [reply] [d/l] |