字符串到数组,用单引号和双引号拆分,忽略转义引号

时间:2012-09-11 01:34:20

标签: php regex preg-split

我有另一个php preg_split问题与my last question非常相似,但我担心解决方案会更复杂一些。像以前一样,我正在尝试使用php将字符串拆分为数组,使用“或”作为分隔符。但除此之外,我想忽略字符串中的转义单引号(字符串中的转义双引号将没有发生所以没有必要担心这一点。)我上一个问题的所有例子仍然有效,但此外还应获得以下两个预期结果:

$pattern = "?????";
$str = "the 'cat\'s dad sat on' the mat then \"fell 'sideways' off\" the mat";
$res = preg_split($pattern, $str, null, PREG_SPLIT_DELIM_CAPTURE);
print_r($res);
/*output:
Array
(
    [0] => the 
    [1] => 'cat\'s dad sat on'
    [2] =>  the mat then
    [3] => "fell 'sideways' off"
    [4] =>  the mat
)*/

$str = "the \"cat\'s dad\" sat on 'the \"cat\'s\" own' mat";
$res = preg_split($pattern, $str, null, PREG_SPLIT_DELIM_CAPTURE);
print_r($res);
/*output:
Array
(
    [0] => the 
    [1] => "cat\'s dad" 
    [2] =>  sat on
    [3] => 'the "cat\'s" own'
    [4] =>  mat
)*/
如果没有转义引用,@ mcrumley对我之前问题的回答很有效:

$pattern = "/('[^']*'|\"[^\"]*\")/U";

然而,只要获得转义的单引号,正则表达式就会将其用作匹配的结尾,这不是我想要的。

我尝试过这样的事情:

$pattern = "/('(?<=(?!\\').*)'|\"(?<=(?!\\').*)\")/";

但它不起作用。不幸的是,我对外观的了解还不够好。

经过一番阅读和摆弄......

这似乎更接近:

$pattern = "/('(?:(?!\\').*)')|(\"(?:(?!\\'|').*)\")/";

但是贪婪程度是错误的,不会产生上述输出。

1 个答案:

答案 0 :(得分:1)

试试这个:

$pattern = "/(?<!\\\\)('(?:\\\\'|[^'])*'|\"(?:\\\\\"|[^\"])*\")/";
             ^^^^^^^^^  ^^^^^^^^^    ^     ^^^^^^^^^^     ^

http://rubular.com/r/Eps2mx8KCw的演示。

您还可以使用反向引用将其折叠为统一表达式:

$pattern = "/(?<!\\\\)((['\"])(?:\\\\\\2|(?!\\2).)*\\2)/";

http://rubular.com/r/NLZKyr9xLk的演示。

如果您还希望在文本中识别转义反斜杠,则这些不起作用,但我怀疑这是您需要考虑的情况。