Instead of juggling around with quotes, take a far superior approach: use a conditional regex.
The basic form is as follows:
(?(1)foo|bar)
# Meaning: if group1 is set, use foo, otherwise bar as subpattern
For your requirements, this comes down to:
--(?P<key>\w+)=(")?(?P<value>(?(2)[^"]+|[^\s]+))
In PHP code and with explanation, this looks even more beautiful:
<?php
$string = 'helloworld --name=stretch --message="Hi there everyone"';
$regex = '~
--(?P<key>\w+)= # look for two dashes, capture every word character into the group "key"
(")? # look for double quotes and make the group (2) optional
(?P<value> # save the following to the group "value"
(?(2)[^"]+|[^\s]+) # if (2) is set, capture everything BUT a double quote
# else capture everything but a space (not allowed without quotes)
)
~x'; # verbose modifier
preg_match_all($regex, $string, $matches, PREG_SET_ORDER);
foreach ($matches as $match)
echo "Key: {$match['key']}, Value: {$match['value']}\n";
/* output:
Key: name, Value: stretch
Key: message, Value: Hi there everyone
*/
?>
See a demo for this one on ideone.com.
You can even go further and allow single quotes as delimiter and have escaped quotes in your values like so:
--(?P<key>\w+)=
(['"])? # allow single or double quotes
(?P<value>
(?(2).+?(?<!\\)(?=\2) # if (2) is set, match everything lazily afterwards
# and make sure that what follows is the formerly captured quote
# make also sure that what precedes, is not a backslash (thus allowing escaped quotes)
|[^\s]+)
)
See this demo on regex101.com (hijacked from @SebastianProske, sorry mate :).
--([a-zA-Z]+)=([^"'\s]+|"[^"]*"|'[^']*')should do it.