regular expression backreferences

M

Marshall Dudley

Given the following:

$string = "start:a-b,c-d,e-f";

$string =~ /start:(?:(\w+)\-(\w+),?)+/;
print "1 -> $1=$2\n2 -> $3=$4\n3 -> $5=$6\n";

I would expect:
1 -> a=b
2 -> c=d
3 -> e=f


but am getting:
1 -> e=f
2 -> =
3 -> =

Is there any way to loop an unknown number of pairs, and get them shoved
into the backreferences instead of them always overwriting the first
two? This is a simplication of the actual problem and I cannot use the
g)lobal designation in the match due to other constraints.

Thanks,

Marshall
 
J

John

Kind of want to know more about the actual problem.

Just based on what's there, my inclination would be to create an
intermediate string, and mark it up to where you could use split.Then
loop through the split results.

But I may be fooled by the stripped-down example here.
 
A

Anno Siegel

Marshall Dudley said:
Given the following:

$string = "start:a-b,c-d,e-f";

$string =~ /start:(?:(\w+)\-(\w+),?)+/;
print "1 -> $1=$2\n2 -> $3=$4\n3 -> $5=$6\n";

I would expect:
1 -> a=b
2 -> c=d
3 -> e=f


but am getting:
1 -> e=f
2 -> =
3 -> =

Is there any way to loop an unknown number of pairs, and get them shoved
into the backreferences instead of them always overwriting the first
two?

No. As you seem to have realized, the correspondence of capturing parens
to $1, $2, ... is static. It depends only on the text of the regex, not
the way it is matched.
This is a simplication of the actual problem and I cannot use the
^^^^^^^^^^^^
... and this is another.
g)lobal designation in the match due to other constraints.

You mention "other constraints", but don't specify them. That makes it
impossible to suggest an alternative.

Anno
 
M

Marshall Dudley

John said:
Kind of want to know more about the actual problem.

Just based on what's there, my inclination would be to create an
intermediate string, and mark it up to where you could use split.Then
loop through the split results.

But I may be fooled by the stripped-down example here.

Well, I am trying to get a mod_rewrite regular expression right for using
in an Apache RewriteRule line. I am testing the line in perl to make sure
it works right before putting it into the apache configuration since it
if it wrong, it could crash the server for everyone and all
applications. I was hoping to get it done in one RewriteRule. Basically
I need to take the form of:

/abc/def-ghi/jkl-mno/..... with any number of terms and convert it to:

cgi-bin/script.cgi?store=abc&def=ghi&jkl=mno....

I was hoping to do it with one RewriteRule, and without the complication
of calling a perl script to do it with, since I have never used the
RewriteRule before and am just now trying to learn/use it. Unfortunately,
I cannot simply test this in the final configuration until I know I have
it right since an error would likely crash the web server for everyone
and everything on the box.

I realize this should be asked in the Apache newsgroups normally, but the
question was on regular expressions, and the knowlege on regular
expressions is much better here.

Thanks,

Marshall
 
E

Eric Schwartz

Marshall Dudley said:
Well, I am trying to get a mod_rewrite regular expression right for using
in an Apache RewriteRule line.
....

I was hoping to get it done in one RewriteRule. Basically
I need to take the form of:

/abc/def-ghi/jkl-mno/..... with any number of terms and convert it to:

cgi-bin/script.cgi?store=abc&def=ghi&jkl=mno....

You might want to go to an Apache group to figure out how to use
regular expressions in an Apache config file; we don't generally know
much about that sort of thing here. However, if you want a Perl
solution, you could use mod_perl on the server, and setup a
PerlTransHandler to rewrite the URI for you. The code in the handler
might look something like (untested, use at your own risk):

sub handler {
my $r = shift;

my $uri = $r->uri;
my ($store, @args);

return Apache::DECLINED if $r->uri =~ m|^/cgi-bin/|;

# strip the store name off the front
$uri =~ s|^/([^/]+)||);
push @args, "store=$1";

# loop over the path components
while($uri =~ m|/([^/]+)|g) {
my $parm = $1;
$parm =~ s/-/=/;
push @args, $parm;
}

# set up the proper url to redirect to
$r->uri('/cgi-bin/script.cgi');
$r->args(join('&', @args));
return Apache::DECLINED;
}

I suppose you could do something fancy with File::Spec::splitdir
instead of looping over the regex the way I did, but I suspect that
might only work on Unix-like systems. A split-based approach would
likely be faster, but I can't be bothered to benchmark it.

This is the first PerlTransHandler I've written, but seemed fairly simple,
based on:

<http://perl.apache.org/docs/2.0/user/handlers/http.html#PerlTransHandler>

Comments from more experienced mod_perl'ers welcome.

-=Eric
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top