an ugly perl regex trick

October 26, 2012 @ 11:21

I haven’t been doing a lot of perl lately, but a lot of my stuff at work is still perl, so every now and then I have to do some maintenance or add new features. Today I was working on new features.

One issue with perl is that there’s no way to get an array of regular expression matches without building it yourself in a really ugly way. I had a situation where I was getting a ‘1’ returned in array of match captures when doing this:

if (my @matches = ($url =~ $test)) {
    ...
}

If there are captures in $test, you get the list of them, but if not, you’ll get a ‘1’ in there, in some cases. Frustrating.

You can do this (Thanks Paul!):

if (my @matches = ($url =~ $test)) {
    @matches = () if @+ < 2;
}

This works great… but in working out what I needed, I decided I wanted to handle both normal captures and named captures. So here’s what I got:

if ($uri =~ $test) {
    # store named matches
    %matches = map {$_ => $+{$_}} keys(%+);

    # store not-named matches by number
    for (my $i=1; $i<= $#-; $i++) {
        $matches{$i} = substr($uri, $-[$i], $+[$i] - $-[$i]);
    }
}

And that is some ugly perl. It works though!