PHPのお勉強!

PHP TOP

preg_split

(PHP 4, PHP 5, PHP 7, PHP 8)

preg_split正規表現で文字列を分割する

説明

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

指定した文字列を、正規表現で分割します。

パラメータ

pattern

検索するパターンを表す文字列。

subject

入力文字列。

limit

これを指定した場合、最大 limit 個の部分文字列を返します。 残りの文字列は、最後の部分文字列に含めて返されます。 limit が -1 あるいは 0 の場合は「制限が無い」ことを意味します。

flags

flags は、次のフラグを組み合わせたものとする (ビット和演算子 | で組み合わせる)ことが可能です。

PREG_SPLIT_NO_EMPTY
このフラグを設定すると、空文字列でないものだけが preg_split() により返されます。
PREG_SPLIT_DELIM_CAPTURE
このフラグを設定すると、文字列分割用のパターン中の カッコによるサブパターンでキャプチャされた値も同時に返されます。
PREG_SPLIT_OFFSET_CAPTURE

このフラグを設定した場合、各マッチに対応する文字列のオフセットも返されます。 これにより、戻り値は配列となり、配列の要素 0 はマッチした文字列、 要素 1subject におけるマッチした文字列のオフセット値となることに 注意してください。

戻り値

pattern にマッチした境界で分割した subject の部分文字列の配列を返します。失敗した場合に false を返します。

エラー / 例外

渡された正規表現のパターンがコンパイルできない場合、E_WARNING が発生します。

例1 preg_split() の例 : 検索文字列のある部分を取得

<?php
// カンマまたは " ", \r, \t, \n , \f などの空白文字で句を分割する。
$keywords = preg_split("/[\s,]+/", "hypertext language, programming");
print_r($keywords);
?>

上の例の出力は以下となります。

Array
(
    [0] => hypertext
    [1] => language
    [2] => programming
)

例2 文字列を文字要素に分割

<?php
$str
= 'string';
$chars = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);
print_r($chars);
?>

上の例の出力は以下となります。

Array
(
    [0] => s
    [1] => t
    [2] => r
    [3] => i
    [4] => n
    [5] => g
)

例3 文字列をマッチするものとそのオフセットに分割

<?php
$str
= 'hypertext language programming';
$chars = preg_split('/ /', $str, -1, PREG_SPLIT_OFFSET_CAPTURE);
print_r($chars);
?>

上の例の出力は以下となります。

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

    [1] => Array
        (
            [0] => language
            [1] => 10
        )

    [2] => Array
        (
            [0] => programming
            [1] => 19
        )

)

注意

ヒント

正規表現の威力を必要としないのなら、より高速な (機能はシンプルですが) 代替関数として explode() あるいは str_split() のような選択肢があります。

ヒント

マッチングに失敗した場合は、要素が一つだけの配列を返します。その要素の内容は、入力文字列そのままになります。

参考

add a note

User Contributed Notes 18 notes

up
43
jan dot sochor at icebolt dot info
15 years ago
Sometimes PREG_SPLIT_DELIM_CAPTURE does strange results.

<?php
$content
= '<strong>Lorem ipsum dolor</strong> sit <img src="test.png" />amet <span class="test" style="color:red">consec<i>tet</i>uer</span>.';
$chars = preg_split('/<[^>]*[^\/]>/i', $content, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
print_r($chars);
?>
Produces:
Array
(
[0] => Lorem ipsum dolor
[1] => sit <img src="test.png" />amet
[2] => consec
[3] => tet
[4] => uer
)

So that the delimiter patterns are missing. If you wanna get these patters remember to use parentheses.

<?php
$chars
= preg_split('/(<[^>]*[^\/]>)/i', $content, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
print_r($chars); //parentheses added
?>
Produces:
Array
(
[0] => <strong>
[1] => Lorem ipsum dolor
[2] => </strong>
[3] => sit <img src="test.png" />amet
[4] => <span class="test" style="color:red">
[5] => consec
[6] => <i>
[7] => tet
[8] => </i>
[9] => uer
[10] => </span>
[11] => .
)
up
20
buzoganylaszlo at yahoo dot com
15 years ago
Extending m.timmermans's solution, you can use the following code as a search expression parser:

<?php
$search_expression
= "apple bear \"Tom Cruise\" or 'Mickey Mouse' another word";
$words = preg_split("/[\s,]*\\\"([^\\\"]+)\\\"[\s,]*|" . "[\s,]*'([^']+)'[\s,]*|" . "[\s,]+/", $search_expression, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
print_r($words);
?>

The result will be:
Array
(
[0] => apple
[1] => bear
[2] => Tom Cruise
[3] => or
[4] => Mickey Mouse
[5] => another
[6] => word
)

1. Accepted delimiters: white spaces (space, tab, new line etc.) and commas.

2. You can use either simple (') or double (") quotes for expressions which contains more than one word.
up
11
canadian dot in dot exile at gmail dot com
9 years ago
This regular expression will split a long string of words into an array of sub-strings, of some maximum length, but only on word-boundries.

I use the reg-ex with preg_match_all(); but, I'm posting this example here (on the page for preg_split()) because that's where I looked when I wanted to find a way to do this.

Hope it saves someone some time.

<?php
// example of a long string of words
$long_string = 'Your IP Address will be logged with the submitted note and made public on the PHP manual user notes mailing list. The IP address is logged as part of the notes moderation process, and won\'t be shown within the PHP manual itself.';

// "word-wrap" at, for example, 60 characters or less
$max_len = 60;

// this regular expression will split $long_string on any sub-string of
// 1-or-more non-word characters (spaces or punctuation)
if(preg_match_all("/.{1,{$max_len}}(?=\W+)/", $long_string, $lines) !== False) {

// $lines now contains an array of sub-strings, each will be approx.
// $max_len characters - depending on where the last word ended and
// the number of 'non-word' characters found after the last word
for ($i=0; $i < count($lines[0]); $i++) {
echo
"[$i] {$lines[0][$i]}\n";
}
}
?>
up
7
Hayley Watson
5 years ago
Assuming you're using UTF-8, this function can be used to separate Unicode text into individual codepoints without the need for the multibyte extension.

<?php

preg_split
('//u', $text, -1, PREG_SPLIT_NO_EMPTY);

?>

The words "English", "Español", and "Русский" are all seven letters long. But strlen would report string lengths 7, 8 and 14, respectively. The preg_split above would return a seven-element array in all three cases.

It splits '한국어' into the array ['한', '국', '어'] instead of the 9-character array that str_split($text) would produce.
up
13
eric at clarinova dot com
13 years ago
Here is another way to split a CamelCase string, which is a simpler expression than the one using lookaheads and lookbehinds:

preg_split('/([[:upper:]][[:lower:]]+)/', $last, null, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY)

It makes the entire CamelCased word the delimiter, then returns the delimiters (PREG_SPLIT_DELIM_CAPTURE) and omits the empty values between the delimiters (PREG_SPLIT_NO_EMPTY)
up
13
Daniel Schroeder
14 years ago
If you want to split by a char, but want to ignore that char in case it is escaped, use a lookbehind assertion.

In this example a string will be split by ":" but "\:" will be ignored:

<?php
$string
='a:b:c\:d';
$array=preg_split('#(?<!\\\)\:#',$string);
print_r($array);
?>

Results into:

Array
(
[0] => a
[1] => b
[2] => c\:d
)
up
1
dewi at dewimorgan dot com
3 years ago
Beware that it is not safe to assume there are no empty values returned by PREG_SPLIT_NO_EMPTY, nor that you will see no delimiters if you use PREG_SPLIT_DELIM_CAPTURE, as there are some edge cases where these are not true.

<?php
# As expected, splitting a string by itself returns two empty strings:
var_export(preg_split("/x/", "x"));

array (
0 => '',
1 => '',
)

# But if we add PREG_SPLIT_NO_EMPTY, then instead of an empty array, we get the delimiter.
var_export(preg_split("/x/", "x", PREG_SPLIT_NO_EMPTY));

array (
0 => 'x',
)

And if
we try to split an empty string, then instead of an empty array, we get an empty string even with PREG_SPLIT_NO_EMPTY.
var_export(preg_split("/x/", "", PREG_SPLIT_NO_EMPTY));

array (
0 => '',
)
?>
up
6
PhoneixSegovia at gmail dot com
14 years ago
You must be caution when using lookbehind to a variable match.
For example:
'/(?<!\\\)\r?\n)/'
to match a new line when not \ is before it don't go as spected as it match \r as the lookbehind (becouse isn't a \) and is optional before \n.

You must use this for example:
'/((?<!\\\|\r)\n)|((?<!\\\)\r\n)/'
That match a alone \n (not preceded by \r or \) or a \r\n not preceded by a \.
up
4
Steve
19 years ago
preg_split() behaves differently from perl's split() if the string ends with a delimiter. This perl snippet will print 5:

my @a = split(/ /, "a b c d e ");
print scalar @a;

The corresponding php code prints 6:

<?php print count(preg_split("/ /", "a b c d e ")); ?>

This is not necessarily a bug (nowhere does the documentation say that preg_split() behaves the same as perl's split()) but it might surprise perl programmers.
up
4
php at dmi dot me dot uk
15 years ago
To split a camel-cased string using preg_split() with lookaheads and lookbehinds:

<?php
function splitCamelCase($str) {
return
preg_split('/(?<=\\w)(?=[A-Z])/', $str);
}
?>
up
7
jetsoft at iinet.net.au
20 years ago
To clarify the "limit" parameter and the PREG_SPLIT_DELIM_CAPTURE option,

<?php
$preg_split
('(/ /)', '1 2 3 4 5 6 7 8', 4 ,PREG_SPLIT_DELIM_CAPTURE );
?>

returns:

('1', ' ', '2', ' ' , '3', ' ', '4 5 6 7 8')

So you actually get 7 array items not 4
up
3