正则表达式(preg_split):如何根据分隔符进行拆分,不包括一对引号中包含的分隔符?

Posted

技术标签:

【中文标题】正则表达式(preg_split):如何根据分隔符进行拆分,不包括一对引号中包含的分隔符?【英文标题】:Regex (preg_split): how do I split based on a delimiter, excluding delimiters included in a pair of quotes? 【发布时间】:2014-09-20 04:40:16 【问题描述】:

我把这个分开了:

1 2 3 4/5/6 "7/8 9" 10

进入这个:

1
2
3
4
5
6
"7/8 9"
10

使用 preg_split()

所以我的问题是,如何根据分隔符进行拆分,不包括一对引号内的分隔符?

我有点想避免首先捕获引号中的内容,理想情况下希望它是一个单行。

【问题讨论】:

【参考方案1】:

您可以使用以下内容。

$text = '1 2 3 4/5/6 "7/8 9" 10';
$results = preg_split('~"[^"]*"(*SKIP)(*F)|[ /]+~', $text);
print_r($results);

解释

在交替运算符的左侧,我们匹配引号中的任何内容,使子模式失败,从而强制正则表达式引擎不使用(*SKIP) and (*F) 的回溯控制重试子字符串。交替运算符的右侧匹配空格字符或不在引号中的正斜杠。

输出

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
    [5] => 6
    [6] => "7/8 9"
    [7] => 10
 )

【讨论】:

也感谢您的解释! 哈哈。起初我将其解释为讽刺,然后我记得这篇文章是针对正则表达式的。特洛洛尔。【参考方案2】:

你可以使用:

$s = '1 2 3 4/5/6 "7/8 9" 10';
$arr = preg_split('~("[^"]*")|[ /]+~', $s, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);

print_r( $arr );

输出:

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
    [5] => 6
    [6] => "7/8 9"
    [7] => 10
)

【讨论】:

+1 用于使用很少出现在答案中的有用 preg_split 标志。 :) 感谢@zx81:在这种情况下,使用这些标志使正则表达式非常简单,也可以在非 PCRE 正则表达式引擎中使用。【参考方案3】:

可选组的另一种方式:

$arr = preg_split('~(?:"[^"]*")?\K[/\s]+~', $s);

模式"[^"]*"[/\s]+ 匹配带引号的部分,后跟一个或多个空格和斜杠。但由于您不想删除引用的部分,因此您在其后添加了 \K\K 从匹配结果中删除左侧已匹配的所有内容。有了这个技巧,当找到引用的部分时,正则表达式引擎只返回空格或斜杠,然后对其进行拆分。

由于在空格或斜线之前并不总是有引号部分,因此您只需使用非捕获组(?:...) 和问号? 使其成为可选

【讨论】:

很好用 \K 这里 +1 您能解释一下表达式中发生了什么吗?感谢您的帮助! @theamydance:我添加了解释。

以上是关于正则表达式(preg_split):如何根据分隔符进行拆分,不包括一对引号中包含的分隔符?的主要内容,如果未能解决你的问题,请参考以下文章

用于根据空格分隔符拆分文本的正则表达式 [重复]

正则表达式

城市字符串----转数组( 加空格---preg_split) 正则分割成数组

如何确保分隔符之间的完整字符串符合正则表达式模式?

PHP正则表达式函数

php正则表达式应用