以下是我尝试运行的代码:
$str = 'a,b,c,d';
return preg_split('/(?<![^\\\\][\\\\]),/', $str);
如您所见,此处使用的正则表达式是:
/(?<![^\\][\\]),/
这是一个简单的固定长度负面观察,因为“前面有一些不是反斜杠的东西,然后是一些东西!”。
这个正则表达式适用于http://www.phpliveregex.com
但是当我去实际尝试运行上面的代码时,我回答了错误:
Warning: preg_split() [function.preg-split]: Compilation failed: lookbehind assertion is not fixed length at offset 13
更糟糕的是,一位程序员在他的5.4.24 PHP服务器上测试了代码,并且运行正常。
这让我相信我的问题与我的服务器配置有关,我几乎无法控制。我被告知我的PHP版本如果5.2。*
是否存在可能没有此问题的preg_replace()的变通方法/替代方法?
答案 0 :(得分:3)
问题是由PCRE 6.7中修复的错误引起的。引用the changelog:
一个被否定的单字符类没有被识别为 固定长度的后续断言,例如
(?<=[^f])
,导致一个 错误的编译错误"lookbehind assertion is not fixed length"
PCRE 6.7于2006年11月在PHP 5.2.0中引入。由于您仍然存在此错误,这意味着它仍然不在您的服务器上 - 因此对于基于preg-split的解决方法,您必须使用没有模式负面的人物类。例如:
$patt = '/(?<!(?<!\\\\)\\\\),/';
// or...
$patt = '/(?<![\x00-\x5b\x5d-\xFF]\x5c),/';
但是,我发现整个方法有点奇怪:如果,
符号前面有三个反斜杠,该怎么办?还是五个?或者他们中的任何奇数?在这种情况下,逗号应该被视为“转义”,但显然你不能创建一个可变长度的lookbehind表达式来覆盖这些情况。
在第二个想法中,可以使用preg_match_all
代替,使用常见的替换技巧来覆盖转义的符号:
$str = 'e ,a\\,b\\\\,c\\\\\\,d\\\\';
preg_match_all('/(?:[^\\\\,]|\\\\(?:.|$))+/', $str, $matches);
var_dump($matches[0]);
Demo。
我真的认为我在这里涵盖了所有问题,那些尾随斜杠是杀手锏)
答案 1 :(得分:1)
避免被否定的字符类的方法(我写\x5c
而不是很多反斜杠更清楚)
$result = preg_split('/(?<!(?!\x5c).\x5c),/s', $str);
关于方法本身:
如果你试图拆分没有转义的逗号,那么你的错误方式就是一个lookbehind,因为你不能在逗号之前检查和定义反斜杠的数量。您有几种方法可以解决这个问题:
$result = preg_split('/(?:[^\x5c]|\A)(?:\x5c.)*\K,/s', $str);
或
$result = preg_split('/(?<!\x5c)(?:\x5c.)*\K,/s', $str);
或用于PHP&gt; 5.2.4
$result = preg_split('/\x5c{2}(*SKIP)(?!)|(?<!\x5c),/s', $str);
答案 2 :(得分:0)
我认为你使用的是较旧的php版本,因为我的错误在 PHP 5.1.6 或更低时出现。
您可以查看 non working demo here
另一方面,它适用于 PHP 5.2.16 或更高版本:
<强> Working demo 强>