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:
$string = "This|is|for|test|";Split it on the pipe character:
@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:
@myarray = split(/\|/, $string, 5);
print Dumper(\@myarray);Now you get:
$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:
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:
@myarray = split(/\|/, $string, -1);
print Dumper(\@myarray);Output:
$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.




