Corey Jeffco
Corey Jeffco

Reputation: 336

Reverse regular expression search

I have a string which contains "foo"s followed by numbers. I'm looking to print the number following the last foo in the string. I've been told that the only way to accomplish this is to reverse the string itself. This isn't very elegant, and I'm surprised Perl doesn't have a better way to get the job done. Is there a better way to do it than this?

#!/usr/bin/perl
# works, but is ugly!!!
$string = "foo1 foo3 foo5 bar foo911 baz";
$string = scalar reverse($string);
$string =~ m/(\d+)oof/;
print scalar reverse("$1");

Upvotes: 3

Views: 13573

Answers (3)

Joel Berger
Joel Berger

Reputation: 20280

I know you already picked an answer but I thought I would add my $0.02.

Why not do a list context global pattern match and take the last element:

#!/usr/bin/perl

use strict;
use warnings;

my $string = "foo1 foo2 foo3 bar";
my @result = $string =~ /foo(\d+)/g;

print pop(@result) . "\n";

Upvotes: 4

Ether
Ether

Reputation: 53966

Here's another solution, inspired by ysth's comment (if it's a very long string and the last foo is near the beginning, resulting in the regex being slow): split the line on 'foo' and parse the last element for the numbers:

my @results = split /foo/, $string;
my ($digits) = ($results[-1] =~ m/^(\d+)/);

Again, I would always go with the simplest code until it looked like the code was taking too long (and this was a problem in the overall application), and then I'd benchmark a number of solutions against typical inputs to see which is best.

Upvotes: 3

CanSpice
CanSpice

Reputation: 35788

How about:

$string =~ /.*foo(\d+)/;

Clarification:

$string =~ /.*     # Match any character zero or more times, greedily.
            foo    # Match 'foo'
            (\d+)  # Match and capture one or more digits.
           /x;

The greedy "any character" match will match the first "foo"s in the string, and you'll be left just matching the last "foo".

Example:

#!perl -w

use strict;
use 5.010;

my $string = "foo1 foo2 foo3";
$string =~ /.*foo(\d+)/;
say $1;

Output:

% perl regex.pl
3

Upvotes: 14

Related Questions