preg_split

Ma Mariya Vinciya Updated 21 Oct 2026
6 min read ·Lesson 162 of 174
In this post

What Is preg_split() ? In simple terms: preg_split() cuts a string into pieces wherever a pattern matches. It works like explode() , but the separator can be a pattern — for example, "any comma, semic

What Is preg_split()?

In simple terms: preg_split() cuts a string into pieces wherever a pattern matches. It works like explode(), but the separator can be a pattern — for example, "any comma, semicolon, or run of spaces" instead of a single fixed character.

Technically: preg_split() returns an array of the substrings found between matches of the pattern. Flags control whether empty pieces are kept, whether the separators themselves are included, and whether offsets are returned. On error, it returns false.

Why Not Just Use explode()?

explode() needs one fixed separator. Real input is often less tidy:

php, mysql;laravel   html

 

Here the items are separated by a comma and space, a semicolon, and several spaces. One preg_split() call handles all of them.


Syntax

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

 

ParameterMeaning
$patternThe separator pattern
$subjectThe string to split
$limitMaximum number of pieces (-1 or 0 \= no limit)
$flagsPREG_SPLIT_NO_EMPTY, PREG_SPLIT_DELIM_CAPTURE, PREG_SPLIT_OFFSET_CAPTURE (combinable with ``)

 


Splitting on Multiple Separators

Example

<?php
$skills = 'php, mysql;laravel   html';

print_r(preg_split('/[\s,;]+/', $skills));

 

Output

Array
(
    [0] => php
    [1] => mysql
    [2] => laravel
    [3] => html
)

 

[\s,;]+ matches any run of whitespace, commas, or semicolons. Using + treats a whole run (such as ", " or three spaces) as one separator, so no empty pieces are created between them.

Splitting Lines Regardless of Line Endings

<?php
$text = "first line\r\nsecond line\nthird line";

print_r(preg_split('/\R/', $text));

 

Output

Array
(
    [0] => first line
    [1] => second line
    [2] => third line
)

 

\R matches any line break: Windows (\r\n), Unix (\n), and old Mac (\r). Text pasted into forms or uploaded files often mixes these, and explode("\n", ...) would leave stray \r characters at the end of lines.


The $limit Parameter

<?php
print_r(preg_split('/,/', 'a,b,c,d', 2));

 

Output

Array
(
    [0] => a
    [1] => b,c,d
)

 

With a limit of 2, the string is split at most once; the last piece contains the rest. This is useful for formats like key: value where the value itself may contain the separator.


Flags

PREG_SPLIT_NO_EMPTY — Remove Empty Pieces

<?php
$input = ',apple,,banana,';

print_r(preg_split('/,/', $input));
print_r(preg_split('/,/', $input, -1, PREG_SPLIT_NO_EMPTY));

 

Output

Array
(
    [0] => 
    [1] => apple
    [2] => 
    [3] => banana
    [4] => 
)
Array
(
    [0] => apple
    [1] => banana
)

 

Leading, trailing, and doubled separators produce empty strings. PREG_SPLIT_NO_EMPTY removes them, and the result is re-indexed.

PREG_SPLIT_DELIM_CAPTURE — Keep the Separators

If the pattern contains a capturing group, the captured separator text is included in the result:

<?php
$expression = '12 + 4*3 - 5';

print_r(preg_split('/\s*([+\-*\/])\s*/', $expression, -1, PREG_SPLIT_DELIM_CAPTURE));

 

Output

Array
(
    [0] => 12
    [1] => +
    [2] => 4
    [3] => *
    [4] => 3
    [5] => -
    [6] => 5
)

 

The expression is split into numbers and operators — a simple tokenizer. \s* around the group absorbs optional spaces, so they are not part of any token. Inside the character class, - and / are escaped because they have special meaning there (range and delimiter).

PREG_SPLIT_OFFSET_CAPTURE — Where Each Piece Starts

<?php
print_r(preg_split('/\s+/', 'one two  three', -1, PREG_SPLIT_OFFSET_CAPTURE));

 

Output

Array
(
    [0] => Array
        (
            [0] => one
            [1] => 0
        )

    [1] => Array
        (
            [0] => two
            [1] => 4
        )

    [2] => Array
        (
            [0] => three
            [1] => 9
        )

)

 

Each piece comes with its starting byte offset in the original string, which is useful for highlighting or editing text in place.


Splitting With Lookarounds

A pattern made only of lookarounds matches a position (zero characters), so the string is split without removing anything.

CamelCase to Words

<?php
$words = preg_split('/(?=[A-Z])/', 'getUserProfileName', -1, PREG_SPLIT_NO_EMPTY);

echo implode(' ', $words) . "\n";
echo strtolower(implode('_', $words)) . "\n";

 

Output

get User Profile Name
get_user_profile_name

 

(?=[A-Z]) matches the position before each uppercase letter. PREG_SPLIT_NO_EMPTY prevents an empty first piece when the string starts with an uppercase letter.

Sentences

<?php
$text = 'PHP is popular. Is it easy to learn? Yes! It powers many websites.';

print_r(preg_split('/(?<=[.!?])\s+/', $text));

 

Output

Array
(
    [0] => PHP is popular.
    [1] => Is it easy to learn?
    [2] => Yes!
    [3] => It powers many websites.
)

 

The lookbehind (?<=[.!?]) keeps the punctuation at the end of each sentence; only the whitespace after it is removed. (Abbreviations such as "e.g." would also be treated as sentence ends; natural language processing needs more advanced tools.)


Splitting Into Characters

<?php
$word = 'Café';

echo count(str_split($word)) . " pieces with str_split()\n";
echo implode(' | ', preg_split('//u', $word, -1, PREG_SPLIT_NO_EMPTY)) . "\n";
echo implode(' | ', mb_str_split($word)) . "\n";

 

Output

5 pieces with str_split()
C | a | f | é
C | a | f | é

 

  • str_split() splits by bytes, breaking the two-byte é into invalid fragments.
  • preg_split('//u', ...) splits between every UTF-8 character. The empty pattern matches every position; u makes the positions character-based.
  • mb_str_split() (PHP 7.4+) does the same more directly and is the recommended choice.

For scripts with combining marks (such as Tamil or Hindi), a "character" as users perceive it may consist of several code points. preg_match_all('/\X/u', $text, $m) collects each visible character (an extended grapheme cluster) in $m[0], and grapheme_str_split() (PHP 8.4+, intl extension) does this directly.


Practical Example: Normalizing Tag Input

Users type tags in many ways — with commas, semicolons, extra spaces, duplicates, and mixed case:

<?php
function parseTags(string $input, int $maxTags = 10): array
{
    $parts = preg_split('/[\s,;]+/u', $input, -1, PREG_SPLIT_NO_EMPTY);

    if ($parts === false) {
        return [];
    }

    $tags = array_map(fn(string $tag): string => mb_strtolower($tag), $parts);
    $tags = array_filter($tags, fn(string $tag): bool => mb_strlen($tag) <= 30);

    return array_slice(array_values(array_unique($tags)), 0, $maxTags);
}

print_r(parseTags('  PHP, MySQL;laravel,,php   Web-Dev ; '));

 

Output

Array
(
    [0] => php
    [1] => mysql
    [2] => laravel
    [3] => web-dev
)

 

Step-by-Step Explanation

  1. preg_split() with PREG_SPLIT_NO_EMPTY splits on any run of separators and drops empty pieces caused by leading, trailing, or doubled separators.
  2. A false result (for example, invalid UTF-8 with u) is handled instead of passed on.
  3. Tags are lowercased with mb_strtolower(), so PHP and php become identical.
  4. Overly long tags are discarded, duplicates are removed, and the list is limited to $maxTags items.

Hyphens are not separators here, so Web-Dev stays one tag.


preg_split() vs explode() vs str_getcsv()

FunctionUse When
explode()A single, fixed separator (faster)
preg_split()Several separators, variable whitespace, or position-based splitting
str_getcsv() / fgetcsv()CSV data with quoted fields ("Chennai, TN" must stay one field)
mb_str_split()Splitting text into characters

 


Common Mistakes

Producing Empty Pieces

Effect: Empty strings in the result from leading, trailing, or repeated separators.

Fix: Use + in the pattern and PREG_SPLIT_NO_EMPTY.

Splitting CSV With a Regex

Effect: Commas inside quoted values break the fields.

Fix: Use str_getcsv() or fgetcsv().

Forgetting the u Modifier for Text

Effect: Character-based splitting breaks multi-byte characters.

Fix: Add u, or use mb_str_split().

Expecting Separators in the Result Without a Group

Effect: PREG_SPLIT_DELIM_CAPTURE has no effect.

Fix: Wrap the separator in a capturing group.

Not Checking for false

Effect: Errors are passed on as false, causing type errors later.

Fix: Check the result before using it.


Best Practices

  • Use explode() for fixed separators and preg_split() when separators vary.
  • Combine + quantifiers with PREG_SPLIT_NO_EMPTY for messy user input.
  • Use \R for line splitting and mb_str_split() for characters.
  • Use PREG_SPLIT_DELIM_CAPTURE for simple tokenizers.
  • Normalize, de-duplicate, and limit the resulting pieces when they come from users.

Official reference: https\://www.php.net/manual/en/function.preg-split.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Home PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope PHP Casting Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence Continue Statement Modify Strings PHP If...Else...Elseif PHP If Modify Strings PHP If Operators PHP Functions Concatenate Strings PHP If...Else User-defined Functions Slicing Strings PHP Shorthand if Escape Characters Default Argument Values PHP Nested if Pass by Reference String Interpolation Named Arguments PHP File Upload Variadic Functions Return Values Search in Strings Multibyte Strings Type Declarations in Functions PHP Numbers PHP Math PHP Floats PHP Random Numbers PHP Constants PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Cookies PHP Destructor PHP Access Modifiers Readonly Properties PHP Sessions PHP Inheritance Method Overriding PHP Filters The final Keyword CSRF Protection PHP Filters Advanced Session Security Secure Cookies PHP Magic Constants File Upload Security PHP Callback Functions PHP Operators Filesystem Security PHP JSON Arithmetic Operators Error Reporting in Production Hiding PHP Assignment Operators PHP Configuration (php.ini) Comparison Operators PHP Command Line (CLI) PHP Exceptions Increment / Decrement Operators Migrating to PHP 8 PHP Form Validation PHP Form Required PHP Form URL/E-mail Error Handling Form Input Sanitizing Escaping Output (htmlspecialchars) Custom Error Handler Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators AJAX PHP AJAX Database AJAX XML AJAX Live Search AJAX Poll AJAX with JSON Security Introduction Password Hashing SQL Injection Prevention XSS Prevention Garbage Collection Project: Simple Blog PHP What is OOP PHP Classes/Objects The $this Keyword Access Array Items Update Array Items Add Array Items Remove Array Items Sorting Arrays Multidimensional Arrays Array Destructuring Array Spread Operator Search in Arrays Merge Arrays PHP Abstract Classes PHP Interfaces Polymorphism PHP Traits PHP Static Methods PHP Static Properties Late Static Binding Magic Methods Object Cloning MySQL Database MySQL Connect MySQL Create DB MySQL Create Table MySQL Insert Data MySQL Get Last ID MySQL Insert Multiple MySQL Prepared MySQL Select Data MySQL Where Debugging PHP Project: Image Upload Gallery $_SESSION $_ENV PHP RegEx RegEx Patterns Heredoc and Nowdoc RegEx Modifiers preg_match preg_replace preg_split PHP RegEx Functions Nullable Types Mixed and Never Types Nullsafe Operator PHP Attributes PHP Fibers Readonly Classes Property Hooks (PHP 8.4) Asymmetric Visibility (PHP 8.4) Reflection API SPL Data Structures Composer
Ask about this post
AI Ask about this post

Ask questions about preg_split and get answers drawn from it.

Signed-in readers only.