Wakan Tanka
Wakan Tanka

Reputation: 8042

Weird behavior of split function

Can somebody please explain following outputs:

Why there are two $VAR1 variables, if it is array with more elements where is $VAR2 ?

$ echo -e "a:b:c\n" | perl -lne 'use Data::Dumper; @a = split(":", $_); print Dumper \@a'
$VAR1 = [
          'a',
          'b',
          'c'
        ];

$VAR1 = [];

Seme output as above instead of reference is printed array, no further element as it was before.

$ echo -e "a:b:c\n" | perl -lne 'use Data::Dumper; @a = split(":", $_); print Dumper @a'
$VAR1 = 'a';
$VAR2 = 'b';
$VAR3 = 'c';

Where does 'undef' comes from? and why again the weird $VAR1?

$ echo -e "a:b:c\n" | perl -lne 'use Data::Dumper; @a = split(":", $_); $b = $a[0]; print Dumper $b'
$VAR1 = 'a';

$VAR1 = undef;

Upvotes: 1

Views: 66

Answers (2)

jwodder
jwodder

Reputation: 57470

The echo command outputs a newline after outputting its argument, so echo -e "a:b:c\n" actually outputs a:b:c\n\n.

Because you're calling Perl with the -l and -n switches, the code will be run twice, once with $_ = "a:b:c", and once with $_ = "", and it's this second run that is producing the $VAR1 = []; and $VAR1 = undef; lines.

The second code snippet doesn't produce any output for the empty input line because @a is empty at that moment, and so Dumper does not have any arguments to print.

Upvotes: 4

ysth
ysth

Reputation: 98388

Echo already adds a trailing newline (unless you specify -n), so you are inputing "a:b:c\n\n", a line with "a:b:c" and a blank line.

Since there are two lines, perl's -n flag's implicit loop is running twice and there are two separate calls to Data::Dumper.

Data::Dumper takes a list of items to dump separately; when you pass it @a rather than \@a, it gets a list of three scalars (for the first line, and an empty list for the second line) to dump independently.

You can set the terse flag to suppress the variable name (except in some cases of recursive structures, I believe):

$Data::Dumper::Terse = 1;
print Dumper ["a".."c"];

yields:

[
  'a',
  'b',
  'c'
]

or explicitly set variable names using the OO interface:

print Data::Dumper->new( [ ["a".."c"], "apple" ], [ "array", "fruit" ] )->Dump();

yields:

$array = [
           'a',
           'b',
           'c'
         ];
$fruit = 'apple';

Upvotes: 6

Related Questions