Homunculus Reticulli
Homunculus Reticulli

Reputation: 68376

How to grok (and modify) this Perl statement

I am new to Perl.

How do I interpret this Perl statement?:

my( $foo, $bar ) = split /\s+/, $foobar, 2;

I know that local variables are being simultaneously assigned by the split function, but I don't understand what the integer 2 is for - I'm guessing the func will return an array with two elements?.

Can a Perl monger explain the statement above to me (ELI5)

Also, on occasion, the string being split does not contain the expected tokens, resulting in either foo or bar being uninitialized and thus causing a warning when an attempt is made to use them further on in the code.

How do I initialize $foo and $bar to sensible values (null strings) in case the split "fails" to return two strings?

Upvotes: 1

Views: 266

Answers (3)

Paul
Paul

Reputation: 27423

The 2 is the maximum number of components returned by split.

Thus, the regexp /\s+/ splits $foobar on clumps of whitespace, but will only split once, to make two components. If there is no whitespace, then $bar will be undefined.

See http://perldoc.perl.org/functions/split.html

In addition to amon's method, Perl has a defined(x) function that returns true or false depending on whether its argument x is defined or undefined, and this can be used in an if statement to correct cases where something is undefined.

See http://perldoc.perl.org/functions/defined.html

Upvotes: 1

user1498339
user1498339

Reputation: 629

As stated here: http://perldoc.perl.org/functions/split.html

"If LIMIT is specified and positive, it represents the maximum number of fields into which the EXPR may be split;"

For example:

#!/opt/local/bin/perl

my $foobar = "A B C D";
my( $foo, $bar ) = split /\s+/, $foobar, 2;

print "\nfoo=$foo";
print "\nbar=$bar";
print "\n";

output:

foo=A
bar=B C D

Upvotes: 0

amon
amon

Reputation: 57600

The split function takes three arguments:

  1. A regex that matches separators, or the special value " " (a string consisting of a single space), which trims the string, then splits at whitespace like /\s+/.

  2. A string that shall be split.

  3. A maximum number of resulting fragments. Sometimes this is an optimization when you aren't interested in all fields, and sometimes you don't want to split at each separator, as is the case here.

So your split expression will return at most two fields, but not neccessarily exactly two. To give your variables default values, either assign default values before the split, or check if they are undef after the split, and give the default:

my ($foo, $bar) = ('', '');
($foo, $bar) = split ...;

or combined

(my ($foo, $bar) = ('', '')) = split ...

or

my ($foo, $bar) = split ...;
$_ //= '' for $foo, $bar;

The //= operator assigns the value on the RHS if the LHS is undef. The for loop is just a way to shorten the code.

You may also want to carry on with a piece of code only when exactly two fields were produced:

if ( 2 == (my ($foo, $bar) = split ...) ) {
  say "foo = $foo";
  say "bar = $bar";
} else {
  warn "could not split!";
}

List assignment in scalar context evaluates to the number of elements assigned.

Upvotes: 4

Related Questions