Reputation: 336
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
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
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
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