preg_split

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

preg_split使用正则表达式拆分字符串

描述

preg_split(
    字符串 $pattern,
    字符串 $subject,
    整数 $limit = -1,
    整数 $flags = 0
): 数组|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 处,以及它在 subject 中的字符串偏移量在偏移量 1 处。

返回值

返回一个数组,其中包含 subject 的子字符串,根据 pattern 匹配的边界拆分,或者在失败时返回 false

错误/异常

如果传递的正则表达式模式未编译为有效的正则表达式,则会发出 E_WARNING 错误。

示例

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

<?php
// 使用任意数量的逗号或空格字符拆分短语,
// 包括 " "、\r、\t、\n 和 \f
$keywords = preg_split("/[\s,]+/", "超文本语言,编程");
print_r($keywords);
?>

上面的示例将输出

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

示例 #2 将字符串拆分为组件字符

<?php
$str
= '字符串';
$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
= '超文本语言编程';
$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()

提示

如果匹配失败,将返回包含单个元素的数组,该元素包含输入字符串。

参见

添加注释

用户贡献的注释 18 个注释

jan dot sochor at icebolt dot info
14 年前
有时 PREG_SPLIT_DELIM_CAPTURE 会产生奇怪的结果。

<?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);
?>
产生
数组
(
[0] => Lorem ipsum dolor
[1] => sit <img src="test.png" />amet
[2] => consec
[3] => tet
[4] => uer
)

因此分隔符模式丢失了。如果您想获取这些模式,请记住使用括号。

<?php
$chars
= preg_split('/(<[^>]*[^\/]>)/i', $content, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
print_r($chars); // 添加了括号
?>
产生
数组
(
[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] => .
)
buzoganylaszlo at yahoo dot com
15 年前
扩展 m.timmermans 的解决方案,您可以使用以下代码作为搜索表达式解析器

<?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);
?>

结果将是
数组
(
[0] => apple
[1] => 熊
[2] => 汤姆·克鲁斯
[3] => 或
[4] => 米老鼠
[5] => 另一个
[6] => 词
)

1. 接受的分隔符:空白字符(空格、制表符、换行符等)和逗号。

2. 对于包含多个单词的表达式,可以使用单引号(')或双引号(")。
canadian dot in dot exile at gmail dot com
8 年前
此正则表达式将把一个长字符串拆分成一个子字符串数组,每个子字符串的最大长度,但只在单词边界上拆分。

我使用正则表达式和 preg_match_all();但是,我把这个例子发布在这里(在 preg_split() 的页面上),因为当我想要找到一种方法来做到这一点时,我就是在这里搜索的。

希望它能节省一些人的时间。

<?php
// 长字符串的示例
$long_string = '您的 IP 地址将与提交的笔记一起记录,并在 PHP 手册用户笔记邮件列表中公开。 IP 地址作为笔记审核过程的一部分记录,不会在 PHP 手册本身中显示。';

// 例如,在 60 个字符或更少的情况下进行“换行”
$max_len = 60;

// 此正则表达式将在任何 1 个或多个非单词字符(空格或标点符号)的子字符串上拆分 $long_string
if(preg_match_all("/.{1,{$max_len}}(?=\W+)/", $long_string, $lines) !== False) {

// $lines 现在包含一个子字符串数组,每个子字符串大约为
// $max_len 个字符 - 取决于最后一个单词的结束位置和
// 最后一个单词之后找到的“非单词”字符的数量
for ($i=0; $i < count($lines[0]); $i++) {
echo
"[$i] {$lines[0][$i]}\n";
}
}
?>
Hayley Watson
4 年前
假设您使用的是 UTF-8,则可以使用此函数将 Unicode 文本分离成单独的代码点,而无需使用多字节扩展。

<?php

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

?>

单词“English”、“Español”和“Русский”都是七个字母长。但是 strlen 会分别报告字符串长度 7、8 和 14。上面的 preg_split 在所有三种情况下都会返回一个七元素数组。

它将“한국어”拆分成数组 ['한', '국', '어'],而不是 str_split($text) 将生成的 9 个字符数组。
eric at clarinova dot com
13 年前
这是另一种拆分 CamelCase 字符串的方法,它比使用前瞻和后顾的表达式更简单

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

它使整个 CamelCased 单词成为分隔符,然后返回分隔符 (PREG_SPLIT_DELIM_CAPTURE) 并省略分隔符之间的空值 (PREG_SPLIT_NO_EMPTY)
Daniel Schroeder
13 年前
如果您想按字符拆分,但希望忽略转义的字符,请使用后顾断言。

在本例中,字符串将按“:”拆分,但“\:”将被忽略

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

结果为

数组
(
[0] => a
[1] => b
[2] => c\:d
)
dewi at dewimorgan dot com
2 年前
请注意,假设 PREG_SPLIT_NO_EMPTY 返回的值中没有空值,或者如果使用 PREG_SPLIT_DELIM_CAPTURE,您将看不到分隔符,这是不安全的,因为在某些边缘情况下,这些情况并非如此。

<?php
# 正如预期的那样,按自身拆分字符串将返回两个空字符串:
var_export(preg_split("/x/", "x"));

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

# 但是,如果我们添加 PREG_SPLIT_NO_EMPTY,那么我们会得到分隔符,而不是空数组。
var_export(preg_split("/x/", "x", PREG_SPLIT_NO_EMPTY));

array (
0 => 'x',
)

如果我们试图拆分一个空字符串,那么我们会得到一个空字符串,而不是空数组,即使使用了 PREG_SPLIT_NO_EMPTY。
var_export(preg_split("/x/", "", PREG_SPLIT_NO_EMPTY));

array (
0 => '',
)
?>
PhoneixSegovia at gmail dot com
13 年前
在使用后顾来匹配变量时,必须小心。
例如
'/(?<!\\\)\r?\n)/'
要匹配换行符,如果它前面没有 \,则不会按预期进行,因为它会匹配 \r 作为后顾(因为它不是 \),并且在 \n 之前是可选的。

您必须使用以下方法,例如
'/((?<!\\\|\r)\n)|((?<!\\\)\r\n)/'
它匹配单独的 \n(前面没有 \r 或 \)或前面没有 \ 的 \r\n。
Steve
19 年前
如果字符串以分隔符结尾,则 preg_split() 的行为与 perl 的 split() 不同。此 perl 代码段将打印 5

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

相应的 php 代码打印 6

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

这不是错误(文档中没有任何地方说明 preg_split() 的行为与 perl 的 split() 相同),但这可能会让 perl 程序员感到惊讶。
php at dmi dot me dot uk
14 年前
使用 preg_split()、前瞻和后顾来拆分驼峰式字符串

<?php
function splitCamelCase($str) {
return
preg_split('/(?<=\\w)(?=[A-Z])/', $str);
}
?>
jetsoft at iinet.net.au
19 年前
为了阐明“限制”参数和 PREG_SPLIT_DELIM_CAPTURE 选项,

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

返回

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

所以您实际上得到了 7 个数组项,而不是 4 个
csaba at alum dot mit dot edu
15 年前
如果任务对于 preg_split 来说太复杂,preg_match_all 可能会有用,因为 preg_split 本质上是一个特例。

我想在某个字符(星号)上拆分一个字符串,但前提是它没有被转义(前面没有反斜杠)。因此,我应该确保任何星号之前的反斜杠数量为偶数,这意味着它是作为分隔符的。正则表达式中的后顾断言不起作用,因为前面反斜杠序列的长度不能固定。因此,我转向 preg_match_all

<?php
// 在非转义星号处拆分字符串
// 其中反斜杠是转义字符
$splitter = "/\\*((?:[^\\\\*]|\\\\.)*)/";
preg_match_all($splitter, "*$string", $aPieces, PREG_PATTERN_ORDER);
$aPieces = $aPieces[1];

// $aPieces 现在包含已拆分的字符串
// 并且可以对每个片段安全地进行转义
foreach ($aPieces as $idx=>$piece)
$aPieces[$idx] = preg_replace("/\\\\(.)/s", "$1", $piece);
?>
david dot binovec at gmail dot com
13 年前
Limit = 1 可能令人困惑。重要的是,在 limit 等于 1 的情况下,只会产生一个子字符串。因此,唯一的一个子字符串将是第一个子字符串,也是最后一个子字符串。字符串的其余部分(第一个分隔符之后)将被放置到最后一个子字符串中。但最后一个是第一个也是唯一的。

<?php

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

echo
$output[0] // 将返回整个字符串!;

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

echo
$output[0] // 将返回 1;
echo $output[1] // 将返回 '2 3 4 5 6 7 8';

?>
Miller
10 年前
这是一个截断文本字符串的函数,同时保留空格(例如,获取文章的摘录,同时保持换行符)。当然,它不适用于 HTML。

<?php
/**
* 按词数截断文本字符串
* @param string $text 要截断的文本
* @param int $max_words 最大单词数
* @return string 被截断的文本
*/
function limit_words ($text, $max_words) {
$split = preg_split('/(\s+)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
$truncated = '';
for (
$i = 0; $i < min(count($split), $max_words*2); $i += 2) {
$truncated .= $split[$i].$split[$i+1];
}
return
trim($truncated);
}
?>
Walf
2 年前
使用 PREG_SPLIT_DELIM_CAPTURE 而不使用 PREG_SPLIT_NO_EMPTY 可以保证结果中所有奇数键都包含分隔符。这使得进一步处理更易预测,并且始终可以在最后过滤掉空字符串。
kenorb at gmail dot com
15 年前
如果你需要转换函数参数,但没有默认值和引用,你可以尝试以下代码

<?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']);
?>
结果:字符串 = "$node,$op,$a3,$form,$a4"
markac
9 年前
将字符串拆分成单词。

<?php
$string
= 'This - is a, very dirty "string" :-)';

// 拆分成单词
$wordlist = preg_split('/\W/', $string, 0, PREG_SPLIT_NO_EMPTY);

// 仅返回至少包含 2 个字符的单词
$wordlist = array_filter($wordlist, function($val) {
return
strlen($val) >= 2;
});

// 打印
var_dump($wordlist);
?>

结果

数组(大小为 5)
0 => 字符串 'This'(长度为 4)
1 => 字符串 'is'(长度为 2)
3 => 字符串 'very'(长度为 4)
4 => 字符串 'dirty'(长度为 5)
5 => 字符串 'string'(长度为 6)
php at haravikk dot me
7 年前
使用 PREG_SPLIT_OFFSET_CAPTURE 选项,最终所有结果都会在一个数组中,这通常是不希望的,因为它意味着你必须过滤掉任何你想检查但不想保留的分隔符。

为了解决这个问题,你可以改为使用 preg_match_all() 来执行拆分。为了比较,这里有两个示例,都以冒号和分号字符为分隔符进行拆分

<?php $pieces_with_delimiters = preg_split('/[;:]/', $input, -1, PREG_SPLIT_OFFSET_CAPTURE); ?>

<?php preg_match_all('/([^;:]*)([;:]|$)/', $input, $matches);
list(,
$pieces, $delimiters) = $matches ?>

后者需要更复杂的模式,但会生成更方便的结果集,具体取决于你想用它们做什么。
To Top