正则表达式用逗号和空格分割字符串,但忽略内部引号和括号

时间:2009-09-03 14:28:19

标签: php regex

我需要用逗号和空格分割字符串,但忽略内部引号,单引号和圆括号

$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

非常感谢

2 个答案:

答案 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)

如果是这样,你面前的工作要困难得多。