Regular expressions7 min readExamples run on PHP 8.5.10

preg_split()

Learn how preg_split() breaks a string at regex matches, how limit and flags change the result, and which mistakes cause empty pieces or false.

Signature

preg_split(string $pattern, string $subject, int $limit = -1, int $flags = 0): array|false

Purpose

preg_split() cuts a string into pieces wherever a regular expression matches. The matched text is the delimiter and is normally thrown away. Use it when the separator is not one fixed string: "any run of commas and spaces", "a digit boundary", or "an operator I also want to keep". If the separator is a fixed string, explode() is simpler and faster. For fixed-size chunks, str_split() is the better tool.

Signature

Parameters and defaults

  • $pattern: a full PCRE pattern including delimiters and optional modifiers, for example '/\s+/'.
  • $subject: the string to split.
  • $limit: the maximum number of pieces. With a positive limit, the remainder of the string is left unsplit in the last piece. -1 and 0 both mean no limit. The default is -1.
  • $flags: a bitmask combined with |. The default 0 sets no flags.

The three flags are:

  • PREG_SPLIT_NO_EMPTY drops empty pieces.
  • PREG_SPLIT_DELIM_CAPTURE also returns text captured by parenthesized groups in the delimiter pattern.
  • PREG_SPLIT_OFFSET_CAPTURE turns every element into a two-item array: the piece and its byte offset in the subject.

Return value and failure

The function returns an array of strings, or an array of [string, offset] pairs when the offset flag is used. It returns false on failure. An invalid pattern emits an E_WARNING and gives false. Runtime problems can also give false; preg_last_error() reports the code. If the pattern never matches, you get an array with one element: the original subject.

Example 1: splitting on a flexible separator

A single pattern can treat commas, spaces and combinations of them as one separator. The + makes consecutive separator characters collapse into one delimiter.

Example
<?php
$parts = preg_split('/[\s,]+/', 'red, green  blue,yellow');
echo json_encode($parts, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
["red","green","blue","yellow"]

Example 2: keeping delimiters and limiting pieces

When you tokenize an expression, the operators matter as much as the operands. A capturing group together with PREG_SPLIT_DELIM_CAPTURE keeps them in the result. The second call shows limit: the last piece holds the unsplit rest.

Example
<?php
$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
$expr = '12+3*4-5';
$tokens = preg_split('/([+*-])/', $expr, -1, PREG_SPLIT_DELIM_CAPTURE);
echo json_encode($tokens, $flags), "\n";
$limited = preg_split('/,/', 'a,b,c,d', 2);
echo json_encode($limited, $flags), "\n";
Output
["12","+","3","*","4","-","5"]
["a","b,c,d"]

Example 3: offsets, empty pieces and characters

Leading, trailing and doubled separators produce empty strings unless you ask for them to be removed. An empty pattern matches between every character, so combined with PREG_SPLIT_NO_EMPTY it splits a string into single bytes.

Example
<?php
$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
echo json_encode(preg_split('/ /', 'ab cd', -1, PREG_SPLIT_OFFSET_CAPTURE), $flags), "\n";
echo json_encode(preg_split('/,/', ',a,,b,'), $flags), "\n";
echo json_encode(preg_split('/,/', ',a,,b,', -1, PREG_SPLIT_NO_EMPTY), $flags), "\n";
echo json_encode(preg_split('//', 'abc', -1, PREG_SPLIT_NO_EMPTY), $flags), "\n";
Output
[["ab",0],["cd",3]]
["","a","","b",""]
["a","b"]
["a","b","c"]

Edge cases

  • Empty pieces are normal. A delimiter at the start or end of the subject produces an empty first or last element. Two adjacent delimiters produce an empty element between them. Add PREG_SPLIT_NO_EMPTY when you do not want these.
  • No match is not failure. You still get an array, containing the whole subject as its only item.
  • Offsets are in bytes. With PREG_SPLIT_OFFSET_CAPTURE, positions count bytes, not characters. This matters for multibyte text.
  • Unicode needs the u modifier. Without it, // splits a multibyte character into separate bytes. With u, an invalid UTF-8 subject can make the call return false.
  • Limit and empty pieces interact. Combined with PREG_SPLIT_NO_EMPTY, the limit applies to non-empty pieces, so check the result when you use both.

Common mistakes

  1. Forgetting delimiters. preg_split(',', $s) is not a valid pattern. Write '/,/'.
  2. Not escaping literal input. If the separator comes from a variable, pass it through preg_quote() with the delimiter character, or use explode() instead.
  3. Ignoring false. Code such as count(preg_split(...)) or foreach over the result is unsafe when the pattern might be invalid or the subject might not be valid UTF-8. Check for false first.
  4. Expecting delimiters to be kept automatically. They are discarded unless a capturing group and PREG_SPLIT_DELIM_CAPTURE are used. A group without the flag does not add anything to the result.
  5. Using regex when plain splitting is enough. A fixed comma separator is clearer and faster with explode(',', $s).
  6. Treating offset results as strings. With PREG_SPLIT_OFFSET_CAPTURE, each element is an array, so strlen($piece) on it will fail.
  • explode() splits by a fixed string.
  • str_split() splits into fixed-length chunks.
  • preg_match() and preg_match_all() extract matches instead of the text between them.
  • preg_replace() rewrites matched text.
  • preg_quote() escapes literal text for use in a pattern.
  • preg_last_error() reports why a PCRE call failed.

Recap

preg_split() splits at regex matches and returns an array, or false on failure. Use limit to cap the pieces, PREG_SPLIT_NO_EMPTY to drop blanks, PREG_SPLIT_DELIM_CAPTURE to keep captured delimiters, and PREG_SPLIT_OFFSET_CAPTURE to get byte positions. Prefer explode() when the separator is a plain string, and always handle the false case.

Tested examples

Split on commas and whitespace
<?php
$parts = preg_split('/[\s,]+/', 'red, green  blue,yellow');
echo json_encode($parts, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
["red","green","blue","yellow"]
Keep delimiters and use a limit
<?php
$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
$expr = '12+3*4-5';
$tokens = preg_split('/([+*-])/', $expr, -1, PREG_SPLIT_DELIM_CAPTURE);
echo json_encode($tokens, $flags), "\n";
$limited = preg_split('/,/', 'a,b,c,d', 2);
echo json_encode($limited, $flags), "\n";
Output
["12","+","3","*","4","-","5"]
["a","b,c,d"]
Offsets, empty pieces and characters
<?php
$flags = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
echo json_encode(preg_split('/ /', 'ab cd', -1, PREG_SPLIT_OFFSET_CAPTURE), $flags), "\n";
echo json_encode(preg_split('/,/', ',a,,b,'), $flags), "\n";
echo json_encode(preg_split('/,/', ',a,,b,', -1, PREG_SPLIT_NO_EMPTY), $flags), "\n";
echo json_encode(preg_split('//', 'abc', -1, PREG_SPLIT_NO_EMPTY), $flags), "\n";
Output
[["ab",0],["cd",3]]
["","a","","b",""]
["a","b"]
["a","b","c"]