PCRE 函数
在线手册:中文  英文

preg_split

(PHP 4, PHP 5)

preg_split通过一个正则表达式分隔字符串

说明

array preg_split ( string $pattern , string $subject [, int $limit = -1 [, int $flags = 0 ]] )

通过一个正则表达式分隔给定字符串.

参数

pattern

用于搜索的模式,字符串形式。

subject

输入字符串

limit

如果指定,将限制分隔得到的子串最多只有limit个,返回的最后一个 子串将包含所有剩余部分。limit值为-1, 0或null时都代表"不限制", 作为php的标准,你可以使用null跳过对flags的设置。

flags

flags 可以是任何下面标记的组合(以位或运算 | 组合):

PREG_SPLIT_NO_EMPTY
如果这个标记被设置, preg_split() 将进返回分隔后的非空部分。
PREG_SPLIT_DELIM_CAPTURE
如果这个标记设置了,用于分隔的模式中的括号表达式将被捕获并返回。
PREG_SPLIT_OFFSET_CAPTURE

如果这个标记被设置, 对于每一个出现的匹配返回时将会附加字符串偏移量. 注意:这将会改变返回数组中的每一个元素, 使其每个元素成为一个由第0 个元素为分隔后的子串,第1个元素为该子串在subject 中的偏移量组成的数组。

返回值

返回一个使用 pattern 边界分隔 subject 后得到 的子串组成的数组。

更新日志

版本 说明
4.3.0 增加了标记PREG_SPLIT_OFFSET_CAPTURE
4.0.5 增加了标记PREG_SPLIT_DELIM_CAPTURE

范例

Example #1 preg_split()示例:获取搜索字符串的部分

<?php
//使用逗号或空格(包含" ", \r, \t, \n, \f)分隔短语
$keywords preg_split("/[\s,]+/""hypertext language, programming");
?>

Example #2 将一个字符串分隔为组成它的字符

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

Example #3 分隔一个字符串并获取每部分的偏移量

<?php
$str 
'hypertext language programming';
$chars preg_split('/ /'$str, -1PREG_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
        )

)

注释

Tip

如果你不需要正则表达式功能,可以有更快(并且更简单)的选择比如 explode()str_split()

参见


PCRE 函数
在线手册:中文  英文

用户评论:

w o z 2 2 a t y a h o o d o t c o m (2011-08-23 03:42:52)

PREG_SPLIT_OFFSET_CAPTURE should be maintained for UTF-8 characters, because it produces wrong results as if it is using strlen() internally, instead of using mb_strlen(), which is the right one...

david dot binovec at gmail dot com (2011-06-26 06:38:28)

Limit = 1 may be confusing. The important thing is that in case of limit equals to 1 will produce only ONE substring. Ergo the only one substring will be the first one as well as the last one. Tnat the rest of the string (after the first delimiter) will be placed to the last substring. But last is the first and only one.

<?php

$output 
$preg_split('(/ /)''1 2 3 4 5 6 7 8'1); 

echo 
$output[0//will return whole string!;

$output $preg_split('(/ /)''1 2 3 4 5 6 7 8'2); 

echo 
$output[0//will return 1;
echo $output[1//will return '2 3 4 5 6 7 8';

?>

eric at clarinova dot com (2011-06-24 15:04:11)

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)

PhoneixSegovia at gmail dot com (2010-11-26 04:38:16)

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 \.

Daniel Schroeder (2010-11-03 03:46:49)

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
)

sergei dot garrison at gmail dot com (2010-03-05 08:04:25)

If you need to split a list of "tags" while allowing for user error, you'll find this more useful than the manual's first example.

<?php
$string 
'one, two,three,     four  , five,six seven';
$array preg_split("/[\s]*[,][\s]*/"$string);
print_r($array);
// Array ( [0] => one [1] => two [2] => three [3] => four [4] => five [5] => six seven )
?>

This splits the string *only* by commas, regardless of how many spaces there are on either side of any comma.

nesbert at gmail dot com (2010-01-28 15:46:38)

Hope this helps someone...

<?php
/**
 * Split a string into groups of words with a line no longer than $max
 * characters.
 *
 * @param string $string
 * @param integer $max
 * @return array
 **/
function split_words($string$max 1)
{
    
$words preg_split('/\s/'$string);
    
$lines = array();
    
$line '';
    
    foreach (
$words as $k => $word) {
        
$length strlen($line ' ' $word);
        if (
$length <= $max) {
            
$line .= ' ' $word;
        } else if (
$length $max) {
            if (!empty(
$line)) $lines[] = trim($line);
            
$line $word;
        } else {
            
$lines[] = trim($line) . ' ' $word;
            
$line '';
        } 
    }
    
$lines[] = ($line trim($line)) ? $line $word;

    return 
$lines;
}
?>

jan dot sochor at icebolt dot info (2009-10-24 03:26:43)

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, -1PREG_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, -1PREG_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] => .
)

php at dmi dot me dot uk (2009-10-06 01:23:58)

To split a camel-cased string using preg_split() with lookaheads and lookbehinds:

<?php
function splitCamelCase($str) {
  return 
preg_split('/(?<=\\w)(?=[A-Z])/'$str);
}
?>

Peter -the pete- de Pijd (2009-09-24 02:34:43)

If you want to use something like explode(PHP_EOL, $string) but for all combinations of \r and \n, try this one:

<?php
$text 
"A\nB\rC\r\nD\r\rE\n\nF";
$texts preg_split("/((\r(?!\n))|((?<!\r)\n)|(\r\n))/"$text);
?>

result:
array("A", "B", "C", "D", "", "E", "", "F");

buzoganylaszlo at yahoo dot com (2009-08-01 00:57:24)

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_expression0PREG_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.

wf (2009-05-28 09:36:25)

Spacing out your CamelCase using preg_replace:

<?php

function spacify($camel$glue ' ') {
    return 
preg_replace'/([a-z0-9])([A-Z])/'"$1$glue$2"$camel );
}

echo 
spacify('CamelCaseWords'), "\n"// 'Camel Case Words'
echo spacify('camelCaseWords'), "\n"// 'camel Case Words'

?>

chris AT cmbuckley DOT co DOT uk (2009-05-27 03:11:11)

Here's a helpful function to space out your CamelCase using preg_split:

<?php

function spacify($camel$glue ' ') {
    return 
$camel[0] . substr(implode($gluearray_map('implode'array_chunk(preg_split('/([A-Z])/',
        
ucfirst($camel), -1PREG_SPLIT_NO_EMPTY PREG_SPLIT_DELIM_CAPTURE), 2))), 1);
}

echo 
spacify('CamelCaseWords'); // 'Camel Case Words'
echo spacify('camelCaseWords'); // 'camel Case Words'

?>

kenorb at gmail dot com (2009-05-23 07:56:27)

If you need convert function arguments without default default values and references, you can try this code:

<?php
    $func_args 
'$node, $op, $a3 = NULL, $form = array(), $a4 = NULL'
    
$call_arg preg_match_all('@(?<func_arg>\$[^,= ]+)@i'$func_args$matches);
    
$call_arg implode(','$matches['func_arg']);
?>
Result: string = "$node,$op,$a3,$form,$a4"

bit_kahuna at yahoo dot com (2009-03-27 11:02:55)

how to display a shortened text string with an elipsis, but on word boundaries only.

<?php
function truncate($string$max 70$rep '...') {

    
$words preg_split("/[\s]+/"$string);
    
    
$newstring '';
    
$numwords 0;
    
    foreach (
$words as $word) {
        if ((
strlen($newstring) + strlen($word)) < $max) {
            
$newstring .= ' '.$word;
            ++
$numwords;
        } else {
            break;
        }
    }

    if (
$numwords count($words)) {
        
$newstring .= $rep;
    }
    
    return 
$newstring;
}
?>

hope this helps someone!  thanks for all the help from everyone else!!

csaba at alum dot mit dot edu (2009-03-17 13:06:20)

If the task is too complicated for preg_split, preg_match_all might come in handy, since preg_split is essentially a special case.

I wanted to split a string on a certain character (asterisk), but only if it wasn't escaped (by a preceding backslash).  Thus, I should ensure an even number of backslashes before any asterisk meant as a splitter.  Look-behind in a regular expression wouldn't work since the length of the preceding backslash sequence can't be fixed.  So I turned to preg_match_all:

<?php
// split a string at unescaped asterisks
// where backslash is the escape character
$splitter "/\\*((?:[^\\\\*]|\\\\.)*)/";
preg_match_all($splitter"*$string"$aPiecesPREG_PATTERN_ORDER);
$aPieces $aPieces[1];

// $aPieces now contains the exploded string
// and unescaping can be safely done on each piece
foreach ($aPieces as $idx=>$piece)
  
$aPieces[$idx] = preg_replace("/\\\\(.)/s""$1"$piece);
?>

anajilly (2008-07-17 01:17:04)

<?php
$s 
'<p>bleh blah</p><p style="one">one two three</p>';

$htmlbits preg_split('/(<p( style="[-:a-z0-9 ]+")?>|<\/p>)/i'$s, -1PREG_SPLIT_DELIM_CAPTURE);

print_r($htmlbits);
?>

Array
(
    [0] =>
    [1] => <p>
    [2] => bleh blah
    [3] => </p>
    [4] =>
    [5] => <p style="one">
    [6] =>  style="one"
    [7] => one two three
    [8] => </p>
    [9] =>
)

two interesting bits:

1. When using PREG_SPLIT_DELIM_CAPTURE, if you use more than one pair of parentheses, the result array can have members representing all pairs.  See array indexes 5 and 6 to see two adjacent delimiter results in which the second is a subset match of the first.

2. If a parenthesised sub-expression is made optional by a following question mark (ex: '/abc (optional subregex)?/') some split delimiters may be captured in the result while others are not.  See array indexes 1 and 2 to see an instance where the overall match succeeded and returned a delimiter while the optional sub-expression '( style="[-:a-z0-9 ]+")?' did not match, and did not return a delimiter.  This means it's possible to have a result with an unpredictable number of delimiters in the result array.

This second aspect is true irrespective of the number of pairs of parentheses in the regex.  This means: in a regular expression with a single optional parenthesised sub-expression, the overall expression can match without generating a corresponding delimiter in the result.

m dot timmermans at home dot NOSPAM dot nl (2008-05-29 03:56:46)

For people who want to use the double quote to group words/fields, kind of like CSV does, you can use the following expression:
<?php
$keywords 
preg_split"/[\s,]*\\\"([^\\\"]+)\\\"[\s,]*|[\s,]+/""textline with, commas and \"quoted text\" inserted"0PREG_SPLIT_DELIM_CAPTURE );
?>
Which will result in:
Array
(
    [0] => textline
    [1] => with
    [2] => commas
    [3] => and
    [4] => quoted text
    [5] => inserted
)

crispytwo at yahoo dot com (2007-09-04 13:29:47)

I was having trouble getting the PREG_SPLIT_DELIM_CAPTURE flag to work because I missed reading the "parenthesized expression" in the documentation :-(
So the pattern should look like:
/(A)/
not just
/A/
and it works as described/expected.

Steve (2005-03-23 08:41:36)

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.

jetsoft at iinet.net.au (2004-09-25 08:01:38)

To clarify the "limit" parameter and the PREG_SPLIT_DELIM_CAPTURE option,

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

returns:

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

So you actually get 7 array items not 4

dave at codewhore dot org (2002-05-29 12:01:45)

The above description for PREG_SPLIT_OFFSET_CAPTURE may be a bit confusing.
When the flag is or'd into the 'flags' parameter of preg_split, each match is returned in the form of a two-element array. For each of the two-element arrays, the first element is the matched string, while the second is the match's zero-based offset in the input string.
For example, if you called preg_split like this:
preg_split('/foo/', 'matchfoomatch', -1, PREG_SPLIT_OFFSET_CAPTURE);
it would return an array of the form:
Array(
[0] => Array([0] => "match", [1] => 0),
[1] => Array([1] => "match", [1] => 8)
)
Note that or'ing in PREG_DELIM_CAPTURE along with PREG_SPLIT_OFFSET_CAPTURE works as well.

易百教程