http://qs1969.pair.com?node_id=1030473

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I'm trying to split x.y into (x,y), but if I see something like x.z.y, I want (x.z,y), not (x,z,y). Basically, I always want the string broken up into 2 substrings - everything up to the last period and everything after. I thought that the following would get the job done:
my $str = "x.z.y" my ($first,$second) = split(/\.[^.]*$/,$str)
but perl has fooled me again! Why is this only returning x.z in $first and nothing in $second? Best Regards, Michael

Replies are listed 'Best First'.
Re: split giving me a splitting headache
by toolic (Bishop) on Apr 24, 2013 at 18:37 UTC
    Then don't use split:
    use warnings; use strict; my $str = "x.z.y"; my ($first, $second) = $str =~ /(.+)\.([^.]+)$/; print "$first,$second\n"; __END__ x.z,y
      Good point. Thanks!
Re: split giving me a splitting headache
by BrowserUk (Patriarch) on Apr 24, 2013 at 18:41 UTC

    Use a lookahead:

    print split '\.(?=[^.]*$)', $_ for 'x.y', 'x.y.z';; x y x.y z

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: split giving me a splitting headache
by kennethk (Abbot) on Apr 24, 2013 at 19:04 UTC
    Why is this only returning x.z in $first and nothing in $second?
    Because split consumes what you are splitting on, and you are splitting on .y in your test case. However,
    If the PATTERN contains capturing groups, then for each separator, an additional field is produced for each substring captured by a group (in the order in which the groups are specified
    so you could do <contrived>
    my $str = "x.z.y"; my ($first,$second) = split(/\.([^.]*)$/,$str);
    </contrived> Other alternatives include split, pop and join; toolic's regex (what I'd actually do); or even reverse, index and substr. Good times.

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: split giving me a splitting headache
by Your Mother (Archbishop) on Apr 24, 2013 at 18:45 UTC

    Or do, :P

    sub split_it_this_a_way { my $string = shift || die "die, die, kill you all!"; my ( $second, $first ) = split '\.', reverse($string), 2; ( ~~reverse($first), $second ); } my $str = "x.z.y"; print $str, " -> ", join(" + ", split_it_this_a_way($str)), $/;

    ...because that's, uh, easier... uh, to, uh...

Re: split giving me a splitting headache
by bart (Canon) on Apr 24, 2013 at 19:21 UTC
    /.*/ is greedy. So all you have to do is
    ($x, $y) = /(.*)\.(.*)/;
    and Bob's your uncle. Unless there is no period. You'll have to handle that case separately.
Re: split giving me a splitting headache
by hdb (Monsignor) on Apr 25, 2013 at 05:24 UTC

    I'd prefer bart's greedy match. But if you want splitting, then split, pop, rejoin:

    use strict; use warnings; my $string = "x.y.z"; my @pieces = split /\./, $string; my $last = pop @pieces; my $first = join ".", @pieces; print "$first $last\n";
split without using split
by space_monk (Chaplain) on Apr 24, 2013 at 19:22 UTC
    Could also try and use a combination of rindex and substr, which may be more efficient.
    If any of my proposed solutions have minor errors, it's because I don't waste my genius on trivial matters. :-P
A reply falls below the community's threshold of quality. You may see it by logging in.