我需要用逗号和空格分割字符串,但忽略内部引号,单引号和圆括号
$str = "Questions, \"Quote\",'single quote','comma,inside' (inside parentheses) space #specialchar";
以便生成的数组具有
[0]Questions [1]Quote [2]single quote [3]comma,inside [4]inside parentheses [5]space [6]#specialchar
我的正式正则表达式是
$tags = preg_split("/[,\s]*[^\w\s]+[\s]*/", $str,0,PREG_SPLIT_NO_EMPTY);
但这忽略了特殊的字符,stil将逗号分隔在引号内,结果数组为:
[0]Questions [1]Quote [2]single quote [3]comma [4]inside [5]inside parentheses [6]space [7]specialchar
ps:这不是csv
非常感谢
答案 0 :(得分:5)
这仅适用于非嵌套括号:
$regex = <<<HERE
/ " ( (?:[^"\\\\]++|\\\\.)*+ ) \"
| ' ( (?:[^'\\\\]++|\\\\.)*+ ) \'
| \( ( [^)]* ) \)
| [\s,]+
/x
HERE;
$tags = preg_split($regex, $str, -1,
PREG_SPLIT_NO_EMPTY
| PREG_SPLIT_DELIM_CAPTURE);
++
和*+
将尽可能多地消耗,并且不会回溯任何回溯。 perlre(1)中描述了这种技术是进行这种匹配的最有效方法。
答案 1 :(得分:2)
嗯,这适用于您提供的数据:
$rgx = <<<'EOT'
/
[,\s]++
(?=(?:(?:[^"]*+"){2})*+[^"]*+$)
(?=(?:(?:[^']*+'){2})*+[^']*+$)
(?=(?:[^()]*+\([^()]*+\))*+[^()]*+$)
/x
EOT;
前瞻断言如果在当前匹配位置之前有任何双引号,单引号或括号,则它们是偶数个,并且这些parens是平衡对(不允许嵌套)。这是一种快速而肮脏的方法,可以确保当前匹配不会出现在一对引号或引号中。
当然,它假设输入结构良好。但就结构良好的问题而言,引号内的报价如何被转义?如果你在parens中有引号,反之亦然怎么办?这项意见是否合法?
"not a \" quote", 'not a ) quote', (not ",' quotes)
如果是这样,你面前的工作要困难得多。