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

I find myself occasionally wanting one element of a split string, without any of the others. In addition, I don't feel the need to save it in memory, because it is only being used on that one line. I've made a subroutine to do basically what I want.
sub hg_split{ my @slice = split($_[1],$_[2]); return $slice[$_[0]]; }
Called like
print hg_split(0,'\.','www.google.com');
Which returns "www". Is there a way to do this without involving a custom subroutine?

Replies are listed 'Best First'.
Re: Split returning one element
by moritz (Cardinal) on Nov 05, 2009 at 18:13 UTC
    print +(split /\./, 'www.google.com', 2)[0];
      Perfect, thank you! Any other neat places where this is helpful?
      Can you elaborate on what is going on with the + sign?
        thing (...) parses a function call, leaving out the + would mean the whole statement is parsed as
        ( print(split ...) )[0]

        Which is not what you want.

        Perl 6 - links to (nearly) everything that is Perl 6.
        print +(split /\./, 'www.google.com', 2)[0];
        is a weird way of writing
        print( (split /\./, 'www.google.com', 2)[0] );
Re: Split returning one element
by toolic (Bishop) on Nov 05, 2009 at 18:13 UTC
    print STDOUT (split /\./, 'www.google.com')[0];
Re: Split returning one element
by AnomalousMonk (Archbishop) on Nov 05, 2009 at 19:52 UTC
    IMHO, the custom function approach is not such a bad way to go. For instance, it allows for data validation, e.g., checking for a negative element index.

    Here's my take on this approach. Note that the  LIMIT parameter of split is used to avoid generating a list of useless substrings. And, of course, the guts of the function can still be extracted and used inline.

    >perl -wMstrict -le "sub my_split { my ($elem, $rx, $string) = @_; return (split $rx, $string, $elem+2)[$elem]; } my $s = 'a:b:c:d:e'; print q{'}, my_split($_, ':', $s), q{'} for 0, 1, 3, 4, 5, 9999; " 'a' 'b' 'd' 'e' '' ''
    Update: Of course, it's always possible to go a little nuts with this kind of thing. Here's a version that returns an arbitrary list of split substrings (but still without much in the way of data validation):
    >perl -wMstrict -le "sub my_split { my $rx = shift; my $string = shift; return unless @_; my $max_i = (sort { $a <=> $b } @_)[-1]; return (split $rx, $string, $max_i+2)[@_]; } my $s = 'a:b:c:d:e'; print my_split(':', $s, 0); print my_split(':', $s, 3, 2); print my_split(':', $s, 5, 4, 9999); print my_split(':', $s); " a dc Use of uninitialized value in print at -e line 1. Use of uninitialized value in print at -e line 1. e
Re: Split returning one element
by keszler (Priest) on Nov 05, 2009 at 18:12 UTC
    my $split_me = 'www.xyz.com'; my $split_char = qr{\.}; $split_me =~ s/$split_char.*$//; # 'www'

    Or to just print the value:

    print $split_me=~/^(.*?)$split_char.*$/;