1

I'm attempting to parse a file containing space-separated key=>value pairs, of a format like so:

host=db test="test test" blah=123

Normally, this file is ingested by Python and parsed using shlex.split, but I've been unable to find a PHP equivalent and my attempts to logic it out with preg_split or strtok haven't been very productive.

Is there a PHP equivalent to Python's shlex.split?

ceejayoz
  • 176,543
  • 40
  • 303
  • 368
  • To my knowledge there are no functions that will produce the exact behavior you are looking for, however, it should be trivial to do this two steps. You can use `preg_match_all` to break the string into an array, then loop through the array, to convert it to the format you need. – datasage Feb 25 '13 at 19:24
  • Something like [Regular expression for matching name value pairs](http://stackoverflow.com/questions/168171/regular-expression-for-parsing-name-value-pairs), except with `,` substituted by `\s` would allow preg_match_all to work. – mario Feb 25 '13 at 19:28

2 Answers2

1

Unfortunately there is no a built in PHP function that natively handles delimited arguments like that. However, you can build one pretty quickly using a little regex and a bit of array walking. This is just an example and only works with the type of string you provided. Any extra conditions will need to be added to the regex to make sure it matches the patterns correctly. You can easily call this function as you iterate through your text file.

/**
 * Parse a string of settings which are delimited by equal signs and seperated by white
 * space, and where text strings are escaped by double quotes.
 *  
 * @param  String $string String to parse
 * @return Array          The parsed array of key/values
 */
function parse_options($string){
    // init the parsed option container
    $options = array();

    // search for any combination of word=word or word="anything"
    if(preg_match_all('/(\w+)=(\w+)|(\w+)="(.*)"/', $string, $matches)){
        // if we have at least one match, we walk the resulting array (index 0)
        array_walk_recursive(
            $matches[0], 
            function($item) use (&$options){
                // trim out the " and explode at the =
                list($key, $val) = explode('=', str_replace('"', '', $item));
                $options[$key] = $val;
            }
        );   
    }

    return $options;
}

// test it
$string = 'host=db test="test test" blah=123';

if(!($parsed = parse_options($string))){
    echo "Failed to parse option string: '$string'\n";
} else {
    print_r($parsed);
}
EmmanuelG
  • 1,051
  • 9
  • 14
  • This is a really bad answer, for what an equivalent of `shlex.split` would be. As it can't even handle `a "b c"` into `["a", "b c"]`. – vallentin Mar 26 '16 at 13:46
0

You can try this PHP version of the shlex extension.

https://github.com/zimuyang/php-shlex

Examples

<?php

$s = "foo#bar";
$ret = shlex_split($s, true);

var_dump($ret);

?>

The above example will output:

array(1) {
  [0] =>
  string(3) "foo"
}
zimuyang
  • 23
  • 2