我想在PHP中拆分包含引用和不带引号的子串的字符串 假设我有以下字符串:
"this is a string" cat dog "cow"
splitted数组应该如下所示:
array (
[0] => "this is a string"
[1] => "cat"
[2] => "dog"
[3] => "cow"
)
我正在用正则表达式进行一些努力,我想知道是否只用一个正则表达式/ preg_split-Call就可以实现......
我尝试的第一件事是:
[[:blank:]]*(?=(?:[^"]*"[^"]*")*[^"]*$)[[:blank:]]*
但是这只能正确地拆分数组[0]和数组[3] - 其余部分按每个字符基础进行拆分。
然后我找到了这个链接:
PHP preg_split with two delimiters unless a delimiter is within quotes
(?=(?:[^"]*"[^"]*")*[^"]*$)
在我看来这是一个很好的起点。但是,我的示例中的结果与第一个正则表达式相同。
我尝试将两者结合起来 - 首先是引用字符串的一个,然后是第二个子正则表达式,它应该省略引用的字符串(因此[^“]):
(?=(?:[^"]*"[^"]*")*[^"]*$)|[[:blank:]]*([^"].*[^"])[[:blank:]]*
因此有2个问题:
答案 0 :(得分:3)
由于匹配不能重叠,您可以像这样使用preg_match_all
:
preg_match_all('/"[^"]*"|\S+/', $input, $matches);
现在$matches[0]
应该包含您要查找的内容。正则表达式将首先尝试匹配带引号的字符串,然后停止。如果没有这样做,它将只收集尽可能多的非空白字符。由于从左到右尝试了替换,因此引用的版本优先。
编辑:但这不会删除引号。为此,您可以使用捕获组:
preg_match_all('/(?|"([^"]*)"|(\S+))/', $input, $matches);
现在$matches[1]
将包含您正在寻找的内容。 (?|
就在那里,以便两个捕获组最终都在同一个索引处。
编辑2:由于您要求preg_split
解决方案,这也是可能的。我们可以使用一个先行,断言空格后跟偶数引号(直到字符串结尾):
$result = preg_split('/\s+(?=(?:[^"]*"[^"]*")*$)/', $input);
当然,这不会删除引号,但可以在单独的步骤中轻松完成。