You need to require something inside the quotes when you do the replace.
$str = '"foo" <[email protected]>';
preg_replace('/"([^"]+)"\s(<.*?>)/', '$1', $str);
preg_replace('/""\s(<.*?>)/', '$1', $str);
Try that. It should leave the address alone if there's no quoted name before it.
Edit: Based on your new example inputs and outputs, try this:
$str = '"foo" <[email protected]>';
preg_replace('/"([^"]+)"\s(<.*?>)/', '$1', $str);
preg_replace('/(?:""\s)?(<.*?>)/', '$1', $str);
It should have the following input/output results:
"foo" <[email protected]> -> foo
"" <[email protected]> -> <[email protected]>
<[email protected]> -> <[email protected]>