如何从preg_split中排除字符串,当字符串已经包含可分割的字符在PHP


How to exclude string from preg_split when string already contains splittable character in PHP?

我在PHP中使用preg_split函数来创建一个包含几个不同元素的数组。但是,我想要排除碰巧包含我要预先分割的元素之一的字符串。

$array['stuff'] = preg_split('/'[#]|' &amp  |' &amp |'&amp |'&amp|' &amp|' &gt  |' &gt |'&gt |'&gt|' &gt|' &  |' & |'& |'&|' &|' '/  |' '/ |''/ |''/|' '/|' >  |' > |'> |'>|' >|' ,  |' , |', |',|', |' ::  |' :: |':: |' ::|'::|' ::|' :  |' : |': |':|' :|' -  |' - |'- |'-|' -/', $array['stuff'] ) ;

我想做的是排除一个字符串,如'foo-bar'被分割匹配,因为它包含一个破折号。'foo-bar'需要完全匹配。

生成的正则表达式将非常复杂,特别是当你有很多像'foo-bar'这样的异常时。

您应该使用一个条件子模式,将向后看作为条件,并将向前看作为yes模式:

$res = preg_split('/(?(?<=foo)'-(?!bar)|'-)/', 'aasdf-fafsdf-foo-bar-asdf' );
var_dump( $res );
结果:

array(4) {
  [0]=>
  string(5) "aasdf"
  [1]=>
  string(6) "fafsdf"
  [2]=>
  string(7) "foo-bar"
  [3]=>
  string(4) "asdf"
}

让我解释一下这里发生了什么。'-意味着

匹配任意破折号

但是我们想要的是

匹配不属于foo-bar的任何破折号。

因为我们不能在正则表达式中实现它,所以我们稍微改变一下:

如果前面有foo而后面没有bar,则匹配中的任何破折号。

要实现if部分,我们使用条件子模式,语法如下:

(?(condition)yes-pattern|no-pattern)

我们的"条件"应该是"前面有foo"来检查,我们使用了后视:

(?<=foo)

如果这是真的,我们应该寻找"后面没有横杠的破折号"来做到这一点,我们使用负向前看:

'-(?!bar)

这就变成了我们的"yes-pattern"。我们的"无模式"应该是'-或"任何破折号"。完整的正则表达式应该是:

(?(?<=foo)'-(?!bar)|'-)

UPDATE:要将其合并到当前的正则表达式中,请更改末尾的这一部分:

|' -  |' - |'- |'-|' -/

|'s?(?(?<=foo)'-(?!bar)|'-)'s?/

虽然我不能保证我的解决方案在这种情况下比nobody的double look - around模式更有效,但我认为我的解决方案更容易阅读。(*SKIP)(*FAIL)有效地匹配并丢弃您希望忽略的子字符串。在某些情况下,这种方法可能非常有用/有效/可维护。

代码(演示):

$string = 'I-like-candy-and-foo-bar-sandwiches';
var_export(preg_split('~foo-bar(*SKIP)(*FAIL)|-~', $string));
输出:

array (
  0 => 'I',
  1 => 'like',
  2 => 'candy',
  3 => 'and',
  4 => 'foo-bar',
  5 => 'sandwiches',
)

老实说,我认为没有人的答案是有点过度设计的。它可以更简单地写成否定的向后看和否定的向前看……没有理由使用条件语法。

代码(演示):

$string = 'I-like-candy-and-foo-bar-sandwiches';
var_export(preg_split('~(?<!foo)-(?!bar)~', $string));
输出:

array (
  0 => 'I',
  1 => 'like',
  2 => 'candy',
  3 => 'and',
  4 => 'foo-bar',
  5 => 'sandwiches',
)

注。如果您可能在输入字符串的开始或结束处有连字符,并且您不希望由preg_split()生成空元素,那么在函数调用中使用0PREG_SPLIT_NO_EMPTY作为参数3和4(分别)。