[Perth-pm] Using \L and \E inside a variable, inside a substitution s///
Peter Hallam
perth.pm at inatick.com
Sun Oct 24 20:34:09 PDT 2010
On Mon, 25 Oct, 08:58 +0800 James Bromberger wrote:
> On 25/10/2010 07:54, Neil Hunt wrote:
> > You can pull out the match (i.e. $1) and pass it through a tr, which
> > should achieve your goal.
> > Something like the following does what you're asking:
> >
> Thanks Neil,
>
> I hadn't through to use TR (face, palm); I was pulling a set of "search"
> and "replace" patterns from a database, and trying to use them all
> generically ALL as a substitution, with this one special case of a case
> change. Its the only time I can see a use for \[LlUu] in place of lc(),
> uc(), etc....
Here's a benchmark of a modified version of my original answer compared to the escaped method:
use 5.12.1;
use Benchmark qw( :all );
my $search = '^([^:]+://[^/]+(:\d+)?)/?(.*)?$'; # From database
my $replace = '\L$1\E/$3'; # From database
$replace =~ s/"/\\"/g; # Protection from embedded code
$replace = '"' . $replace . '"'; # Put in a string for /ee
my @urls = qw ( http://www.FOo.COm:80/wibbLE http://www.FOo.COm/ http://www.FOo.COm );
for my $url (@urls) {
my ( $result_escape, $result_lc );
say "URL = $url";
cmpthese( -1, {
'Escape' => sub { $url =~ s/$search/$replace/ee; },
'lc' => sub {
$url =~ m|([^:]+://[^/]+(:\d+)?)/?(.*)?$|;
$result_lc = sprintf "%s%s/%s\n",
lc $1
, ( $2 ? ":$2" : '' )
, ( $3 ? $3 : '' );
},
} );
print "\n";
say "Escape: $url";
say " lc: $result_lc";
print "\n\n";
}
There's a couple of orders of magnitude difference here, something worth considering.
I've also looked at Neil's regex, which is slightly faster by about 2%, and I've also looked at the tr// method, which is slower by about 10%
Finally, if you want a concise (but slow) piece of code, I came up with:
$url =~ s|([^:]+://[^/]+(:\d+)?/?)?(.*)?$|\L$1\E$3|;
Regards,
Peter.
More information about the Perth-pm
mailing list