The Split() Trap: Why Perl Was Eating My Empty Fields

I was working on a data-matching project. One organisation sending data to match against another. Standard stuff: plain text, fields separated by a delimiter (tab, in this case).

I reached for Perl’s split function to break each line into an array. Simple enough. Except split has a quirk that bit me hard: if the last field in your record is empty, split just… drops it.

That meant any record missing its final value came back one element short. My matching logic assumed a fixed number of fields, so this quietly broke everything.

The Problem, Illustrated

Take this string:

Perl
$string = "This|is|for|test|";

Split it on the pipe character:

Perl
@myarray = split(/\|/, $string);
print Dumper(\@myarray);

You’d expect five elements — four words plus an empty string for whatever comes after that trailing pipe. Instead, you get four:

$VAR1 = [
          'This',
          'is',
          'for',
          'test'
        ];

That trailing empty field just vanishes.

First Fix: Force a Limit

split takes an optional third argument — a limit on how many pieces to split into. Set it explicitly, and Perl stops trimming:

Perl
@myarray = split(/\|/, $string, 5);
print Dumper(\@myarray);

Now you get:

Perl
$VAR1 = [
          'This',
          'is',
          'for',
          'test'
        ];

That works — but only if you already know how many fields to expect. I didn’t. Field counts varied by record.

Second Fix: Count the Delimiters Myself

So I got clever. I used Perl’s tr operator — normally used to transliterate or count characters — to count how many pipes were in the string, then fed that count (plus one) into split as the limit:

Perl
my $count = $string =~ tr/\|//;
@myarray = split(/\|/, $string, $count + 1);
print Dumper(\@myarray);

tr/// without a replacement just counts occurrences without changing anything, which made it perfect for this. It worked. My array came back the right length every time, empty trailing field included.

I was pretty pleased with myself.

Then I Found the Actual Answer

Turns out split already solves this — you just have to know the trick.

Pass -1 as the limit, and Perl stops stripping trailing empty fields entirely. No counting delimiters. No tr gymnastics. One argument:

Perl
@myarray = split(/\|/, $string, -1);
print Dumper(\@myarray);

Output:

Perl
$VAR1 = [
          'This',
          'is',
          'for',
          'test',
          ''
        ];

Same result as my elaborate tr-counting workaround — except it’s a single, built-in argument instead of two extra lines of logic.

The Real Lesson: RTFM

Here’s the part that actually stings. This behaviour isn’t some obscure edge case buried in a forum post somewhere. It is in perldoc -f split, plain as day. A negative limit means “keep all trailing empty fields.” It’s been documented since forever.

I burned an afternoon reasoning my way to a workaround for a problem Perl’s own manual had already solved in one sentence. All I had to do was read it.

So consider this the real takeaway, more than any of the code above: before you write your own clever fix, check the documentation for the function you’re already using. Half the “gotchas” we discover the hard way turn out to be a paragraph in the docs we skipped past.

Leave a Reply