split has sharp edges¶
Level: 101 · you will hit this in your first week
One line: split always takes a pattern — split ".", "1.2.3" splits on every character and returns nothing — it drops trailing empty fields unless the limit is -1, returns no fields at all for an empty string, treats a single space ' ' as "runs of whitespace", returns captured separators as fields, and quietly limits itself to the number of variables you assign to.
Measured¶
Verified output of split_pl.pl — regenerated by tools/run_examples.py, never hand-typed.
--- empty fields ---
split /,/, "a,b,," 2: ("a", "b")
split /,/, "a,b,,", -1 4: ("a", "b", "", "")
split /,/, ",a,b" 3: ("", "a", "b")
split /,/, "" 0: ()
--- the first argument is a pattern ---
split ".", "1.2.3" 0: ()
split /\./, "1.2.3" 3: ("1", "2", "3")
split $sep, "a|b" 3: ("a", "|", "b") $sep is "|"
split /\Q$sep\E/, "a|b" 2: ("a", "b")
--- one space is special ---
split ' ', " two words " 2: ("two", "words")
split / /, " two words " 5: ("", "", "two", "", "words")
split /\s+/, " two words " 3: ("", "two", "words")
--- groups in the pattern come back as fields ---
split /(,)/, "a,b" 3: ("a", ",", "b")
split /(-)|(,)/, "a-b,c" 7: ("a", "-", undef, "b", undef, ",", "c")
--- the number of fields you asked for ---
my ($key, $value) = split /=/, 'next=/search?q=perl' $value is "/search?q"
my ($key, $value) = split /=/, 'next=/search?q=perl', 2 $value is "/search?q=perl"
my $count = () = split /,/, "a,b,c,d" $count is 1
my $count = split /,/, "a,b,c,d" $count is 4
Empty fields¶
- At the end they vanish.
"a,b,,"is four fields, the last two empty;splitreturns two. A row whose last columns are empty becomes a shorter array. The limit-1keeps them. - At the start they stay.
",a,b"gives an empty first field. - An empty string gives no fields — an empty list, not one empty field.
The first argument is a pattern¶
A string is compiled as a regex, so split "." splits on any character: every field is empty, and then rule one deletes them all. split /\./ is the literal dot. The same trap with a variable is worse, because nothing looks wrong: $sep = '|' is a pattern of two empty alternatives, which matches between every character. \Q...\E quotes a variable's metacharacters.
One space is special¶
split ' ' — a string holding exactly one space — splits on runs of whitespace and skips leading whitespace. It is what -a uses in a one-liner. split / / splits on each single space and keeps every empty field between them, and split /\s+/ still leaves an empty first field for the leading spaces.
Groups come back¶
Every capture group in the pattern is returned as a field between the pieces. With two groups of which only one matches, the other is returned as undef.
The limit you did not ask for¶
When split is assigned to a list of variables, perl gives it a limit of one more than the number of variables. my ($key, $value) = split /=/, 'next=/search?q=perl' splits into at most three fields — next, /search?q, perl — and throws the third away, so $value has lost its =perl. A limit of 2 keeps the rest together.
The same rule makes my $count = () = split ... return 1: an empty list is zero variables, so the limit is one, and one field is the whole string. split in scalar context counts correctly.
What to do instead¶
my @fields = split /,/, $line, -1; # a separator you chose: keep every field
my @words = split ' ', $text; # words
my ($key, $value) = split /=/, $pair, 2; # a key, and all the rest
my @parts = split /\Q$sep\E/, $s, -1; # a separator held in a variable
For CSV, use none of these — see CSV is not split.
If you are coming from another language¶
- Java.
String.splitcopied the trailing-field rule and the regex argument, but not the empty string:"".split(",")has length 1 in Java, where Perl returns nothing. Seesplithas sharp edges ↗. - Rust.
str::split↗ always returns n + 1 pieces for n matches, keeping every empty one; Splitting on nothing ↗ and Walking aString↗ cover the rest. - Python.
str.split(',')keeps every field and takes a literal string, not a pattern;str.split()with no argument issplit ' '.
See also¶
-l,-aand-Ftake a line apart —splitas a one-liner switch- split ↗