regex - PHP split comma-separated values but retain quotes


Keywords:php 


Question: 

I'm trying to split a string that contains comma-separated set of values. This can be achieved simply by using str_getcsv but I have an additional requirement where it falls short of. I need to retain quotes.

With an input string of:

string(30) "Hello, "San Diego, California""

I tried two approaches:

explode

$result = explode(",", $string);

Which results in

array(3) {
  [0]=>
  string(5) "Hello"
  [1]=>
  string(11) " "San Diego"
  [2]=>
  string(12) " California""
}

str_getcsv

$result = str_getcsv($string, ",");

This one results in

array(2) {
  [0]=>
  string(5) "Hello"
  [1]=>
  string(21) "San Diego, California"
}

I prefer using str_getcsv because it splits the values properly but it trims the enclosing quotes out. I need those quotes so I'm hoping I could call the function without it automatically removing the quotes.

Additional Info

I am actually open for a regex solution but I am clueless in that area.


I tried the solution here and it didn't work.


2 Answers: 

This pushed the limits of my regex knowledge, and I was unable to come up with an elegant regex which covers all possible cases for the input string (e.g. If the string ends with a comma) without leaving empty matches at the end.

$parts = preg_split('/(?:"[^"]*"|)\K\s*(,\s*|$)/', $string);

By itself, this gives:

Array
(
    [0] => Hello
    [1] => "San Diego, California"
    [2] => 
)

So this is required to clean-up 1-2 empty elements matched at the end (depending on the input string), if you don't want those:

$i = count($parts);
while ($i) {
    if ($parts[--$i] == '') {
        unset($parts[$i]);
    } else {
        break;
    }
}

Note: The regex trims white-space from the start/end of each match. Remove the \s* parts if you don't want that.

 
$wrapped = array_map(function($value) { 
   return "\"$value\"";
}, str_getcsv($string, ","));

UPDATE: You could try something like this:

$value = preg_split('~(?:\'[^\']*\'|"[^"]*"|)\K(,|$)~', $string);

I lifted this from PHP get comma separated values which are not enclosed