Split up a search string of "field names"="some values"

I want to convert/parse the following string:

$search_term = ' "full name"="john smith" city="london" foo bar baz ';

Basically the search term are any number of field=value pairs, separated by spaces. Ideally they should then be an array:

$array['full name'] = 'john smith';
$general = 'foo bar baz';

'foo bar baz' should go into a $general variable.

I was thinking chop on spaces and avoid regex but not so sure now.

Answers


How about this new version:

$str = ' foo "full name"="john smith" bar city="london" baz ';

preg_match_all('/(?:"([^"]+)"="([^"]+)")|(?:([^= ]+)="([^"]+)")|([^"= ]+ )/', $str, $m);
$res = array();

for($i=0; $i < count($m[2]); $i++) {
    if (empty($m[1][$i]) && empty($m[3][$i])) {
        $res['general'] .= $m[5][$i];
    } elseif (!empty($m[1][$i])) {
        $res[$m[1][$i]] = $m[2][$i];
    } else {
        $res[$m[3][$i]] = $m[4][$i];
    }
}
print_r($res);

Output:

Array
(
    [general] => foo bar baz 
    [full name] => john smith
    [city] => london
)

While this is not a particularly elegant solution, it should work quite well. In essence you first replace the quoted strings, find the search terms and then replace it back.

$search_term = ' "full name"="john smith" city="london" foo bar baz ';

$replace = array();
// find all quoted strings
preg_match_all('#"[^"]+"#', $search_term, $matches);

// and replace them with something temporary
foreach ($matches[0] as $k => $match) $replace[$match] = "quo" . $k . "ted";

$search_term_without_quotes = str_replace(array_keys($replace), array_values($replace), $search_term);

$terms = explode(' ', $search_term_without_quotes);

$array = array();
$general = "";
foreach ($terms as $term) {
    // replace it back (notice the reversed array_values and array_keys
    $term = str_replace(array_values($replace), array_keys($replace), $term);
    // explode into two fields
    // if an = can be in the first quoted term you need to move the replacing further down
    $term = explode("=", $term, 2);

    if (count($term) == 1) {
        $general .= " " . trim($term[0], '"');
    } else {
        $array[trim($term[0], '"')] = trim($term[1], '"');
    }
}
print_r($array);
print_r($general);

This gives you:

Array
(
    [full name] => john smith
    [city] => london
)
foo bar baz 

Try this:

function parse($str) {
    function mytrim($str) {
        return trim($str, '"');
    }
    $rx = '/("[^"]*"|\S+)\=("[^"]*"|\S+)/s';
    $a_ret1 = preg_match_all($rx, $str, $arr)?
        array_combine(array_map('mytrim', $arr[1]), array_map('mytrim', $arr[2])) : array();
    $str = preg_replace($rx, '', $str);
    $a_ret2 = preg_match_all('/([^\s"]+)/s', $str, $arr)? $arr[1] : array();
    return array($a_ret1, $a_ret2);
}

$search_term = ' "full name"="john smith" city="london" foo bar baz ';
list($a1, $a2) = parse($search_term);
echo 'result 1: '. print_r($a1, true);
echo 'result 2: '. print_r(implode(' ', $a2), true);

Demo


Need Your Help

STM32F4 SPI issue

c embedded stm32 spi

I'am using STM32F407vg and i'am trying to write data in SPI data register, the following code shows the configuration function