Is there a native \"PHP way\" to parse command arguments from a string
? For example, given the following string
:
foo \"bar \\\"baz
Regexes are quite powerful: (?s)(?. So what does this expression mean ?
(?s)
: set the s
modifier to match newlines with a dot .
(? : negative lookbehind, check if there is no backslash preceding the next token
("|')
: match a single or double quote and put it in group 1(?:[^\\]|\\.)*?
: match everything not \, or match \ with the immediately following (escaped) character\1
: match what is matched in the first group|
: or\S+
: match anything except whitespace one or more times.The idea is to capture a quote and group it to remember if it's a single or a double one. The negative lookbehinds are there to make sure we don't match escaped quotes. \1
is used to match the second pair of quotes. Finally we use an alternation to match anything that's not a whitespace. This solution is handy and is almost applicable for any language/flavor that supports lookbehinds and backreferences. Of course, this solution expects that the quotes are closed. The results are found in group 0.
Let's implement it in PHP:
$string = <<
If you wonder why I used 4 backslashes. Then take a look at my previous answer.
Output
Array
(
[0] => foo
[1] => "bar \"baz\""
[2] => '\'quux\''
[3] => 'foo"bar'
[4] => "baz'boz"
[5] => hello
[6] => "regex
world\""
[7] => "escaped escape\\"
)
Online regex demo Online php demo
Removing the quotes
Quite simple using named groups and a simple loop:
preg_match_all('#(?(?:[^\\\\]|\\\\.)*?)\1|(?\S+)#s', $string, $matches, PREG_SET_ORDER);
$results = array();
foreach($matches as $array){
if(!empty($array['escaped'])){
$results[] = $array['escaped'];
}else{
$results[] = $array['unescaped'];
}
}
print_r($results);
Online php demo