Re: Simple way to split on last match?
by Marshall (Canon) on Aug 05, 2012 at 19:22 UTC
|
In Perl, you can use the index of [-1] to indicate the last array element. A REGEX would work fine here also. I don't know without benchmarking, but I suspect that the regex version is actually faster.
#!/usr/bin/perl -w
use strict;
my $line ='last -- From --00--SPLIT ?--11452';
my ($last) = (split(/--/, $line))[-1];
print "using split: $last\n";
($last) = $line =~ /(\d+)\s*$/;
print "using regex: $last\n";
__END__
Prints:
using split: 11452
using regex: 11452
Update: I guess I should say that the parens around ($last) are necessary to put $last into a list context, otherwise you just get 1 or 0 value. Here we want the actual value that was captured rather than whether it the expression "worked" or "not.
| [reply] [d/l] [select] |
|
|
Hey thanks!
my ($last) = (split(/--/, $line))-1;
Works
The -1 is what is significant in getting the last one i guess.
-Turtle
| [reply] |
|
|
Yes that is correct.
A Perl "list slice" can have indices of [-3,2,-1,3,-4] in any order.
The one thing that I wish Perl could do that it cannot do: is to say "I want all of the stuff past index X" in a simple syntax.
| [reply] [d/l] |
Re: Simple way to split on last match?
by johngg (Canon) on Aug 05, 2012 at 22:02 UTC
|
Another way to do it, since your delimiter is invariate, would be to use substr and rindex.
[johngg@justy Documents]$ perl -E '
> $str = q{last -- From --00--SPLIT ?--11452};
> $delim = q{--};
> $last = substr $str, rindex( $str, $delim ) + length $delim;
> say $last;'
11452
[johngg@justy Documents]$
I hope this is helpful.
| [reply] [d/l] |
Re: Simple way to split on last match?
by aaron_baugher (Curate) on Aug 06, 2012 at 02:16 UTC
|
Like others, I immediately reach for (split)[n] in a situation like this, so I thought I'd benchmark that against the other ideas offered in this thread. split was more than twice as fast as a regex, which wasn't a surprise, but johngg's combination of substr and rindex stomped it. The first run below used the sample string given by the OP, and then I ran it again using a string 32 times as long (with 32 times the delimiters). The substr/rindex solution only gets better with length. Have to remember that one!
# with a short string
regex it 520833/s -- -56% -88%
split it 1176471/s 126% -- -73%
index it 4347826/s 735% 270% --
# with a long string
Rate regex it split it index it
regex it 20053/s -- -68% -100%
split it 62004/s 209% -- -99%
index it 4784689/s 23761% 7617% --
Aaron B.
Available for small or large Perl jobs; see my home node.
| [reply] [d/l] [select] |
Re: Simple way to split on last match?
by tobyink (Canon) on Aug 05, 2012 at 20:38 UTC
|
Personally I'd use split to split on all matches, then grab the last element from the resulting array. If you need the first part all as one piece, then you can use join to stitch it back together.
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
| [reply] [d/l] [select] |
Re: Simple way to split on last match?
by nemesdani (Friar) on Aug 05, 2012 at 19:30 UTC
|
| [reply] [d/l] |
Re: Simple way to split on last match?
by Anonymous Monk on Aug 06, 2012 at 14:33 UTC
|
I like to use several regexes ... if you want the string at the end, $ will anchor to the end-of-string. If you can't easily say it in one regex, use several. If split() seems natural, just do it, then pop the result off the end. In the long run it probably will not make the slightest bit of difference which way you do it, as long as it can be proved to work correctly with all possible inputs that it will encounter and if it is abundantly clear to the human eye. (Literally... use Test::Most to construct a thorough test-case which will prove that the parsing algorithm you selected will always accept valid strings and will always reject invalid ones. | [reply] |