Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

Simple way to split on last match?

by aturtle (Novice)
on Aug 05, 2012 at 19:07 UTC ( #985564=perlquestion: print w/replies, xml ) Need Help??
aturtle has asked for the wisdom of the Perl Monks concerning the following question:

Is there a simple way to use perl split to just use the last match? If for example I wanted to split everything (11452) after the last -- From --00--SPLIT ?--11452 ignoring any characters before the last -- Or should I just use a regex for that? Thanks in advance

Replies are listed 'Best First'.
Re: Simple way to split on last match?
by Marshall (Abbot) 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.
      Hey thanks! my ($last) = (split(/--/, $line))-1; Works The -1 is what is significant in getting the last one i guess. -Turtle
        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.
Re: Simple way to split on last match?
by johngg (Abbot) 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.



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.

Re: Simple way to split on last match?
by tobyink (Abbot) 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'
Re: Simple way to split on last match?
by nemesdani (Friar) on Aug 05, 2012 at 19:30 UTC
    I don't quite understand your problem. However you could check out the @- (LAST_MATCH_START) variable at perlvar, maybe it helps.

    I'm too lazy to be proud of being impatient.
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.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://985564]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2018-04-25 03:41 GMT
Find Nodes?
    Voting Booth?