用逗号分割字符串,但有异常

时间:2017-12-04 09:10:28

标签: php regex

我有一个带有颜色名称的字符串,以逗号或|分隔字符:

$s = 'Blue | Red (light, dark) | Green, Yellow, Brown';

我需要将其转换为数组:

$colors = preg_split('![\|,]!', $s);

但结果是:

Array
(
    [0] => Blue 
    [1] =>  Red (light
    [2] =>  dark) 
    [3] =>  Green
    [4] =>  Yellow
    [5] =>  Brown
)

用逗号分隔“浅,暗”字符串。我想用括号内的逗号分隔。期望的结果:

Array
(
    [0] => Blue 
    [1] =>  Red (light, dark) 
    [2] =>  Green
    [3] =>  Yellow
    [4] =>  Brown
)

我该如何解决?

3 个答案:

答案 0 :(得分:2)

$str = 'Blue | Red (light, dark) | Green, Yellow, Brown (light | bright)';
$res = preg_split('/
                     (          # group 1
                       [^|,]*   # 0 or more not pipe or comma
                       \(       # open parenthesis
                       [^()]*   # 0 or more not parenthesis
                       \)       # close parenthesis
                     )          # end group 1
                    |           # OR
                     [|,]       # a pipe or a comma
                   /x', 
                   $str, -1,
                    PREG_SPLIT_NO_EMPTY
                  | PREG_SPLIT_DELIM_CAPTURE);
print_r($res);

<强>输出:

Array
(
    [0] => Blue 
    [1] =>  Red (light, dark)
    [2] =>  
    [3] =>  Green
    [4] =>  Yellow
    [5] =>  Brown (light | bright)
)

答案 1 :(得分:1)

您需要在替换之前屏蔽输入字符串的括号部分:

$s = 'Blue | Red (light, dark) | Green, Yellow, Brown';

// Mask the parenthesed sections.
// Replace the ',' character with a unique string which you can guarantee will not occur (here: '===')
$sr =
    preg_replace_callback(
       '!\([^\)]+\)!'
     , function ( $p_hit ) { return str_replace(',', '===', $p_hit[0]); }
     , $s
    );

// original split
$colors = preg_split('![\|,]!', $sr);

// undo masking 
$colors = array_map (
    function ($elem) { return str_replace('===', ',', $elem); }
  , $colors
);

// Print result
print_r ($colors);

输出:

Array
(
[0] => Blue 
[1] => Red (light, dark) 
[2] => Green
[3] => Yellow
[4] => Brown
)

注意

此解决方案不适用于包含嵌套括号的源字符串。

答案 2 :(得分:0)

您只需要使用(*SKIP)(*FAIL)取消括号内的分隔符。我还在分隔符之前和之后添加了零个或多个空格,以便修剪输出值。

代码:(Demo

$s = 'Blue | Red (light, dark) | Green, Yellow, Brown';
$colors = preg_split('/\([^)]+(*SKIP)(*FAIL)|\s*[,|]\s*/',$s);
var_export($colors);

echo "\n";

$str = 'Blue | Red (light, dark) | Green, Yellow, Brown (light | bright)';
$colors = preg_split('/\([^)]+(*SKIP)(*FAIL)|\s*[,|]\s*/',$str);
var_export($colors);

输出:

array (
  0 => 'Blue',
  1 => 'Red (light, dark)',
  2 => 'Green',
  3 => 'Yellow',
  4 => 'Brown',
)
array (
  0 => 'Blue',
  1 => 'Red (light, dark)',
  2 => 'Green',
  3 => 'Yellow',
  4 => 'Brown (light | bright)',
)

为了争论,您可以在样本输入字符串上使用它:

var_export(preg_match_all('/[a-z]+(?: \([^)]+\))?/i',$str,$out)?$out[0]:'fail');

这种情况不区分地匹配颜色,然后可选地包括尾随的括号表达式。相同的输出。