[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