Вы можете отменить нежелательные побеги.
$str = preg_quote($str, '/');
$str = str_replace(['\\*', '\\\\'], ['*', '\\'], $str);
Это может быть функция:
function preg_quote_except($str, $except, $delim = NULL) {
$str = preg_quote($str, $delim);
for ($i = 0; $i < strlen($except); $i++) {
$from[] = '\\' . $except[$i];
$to[] = $except[$i];
}
return str_replace($from, $to, $str);
}
Тогда вы бы назвали это как:
$str = preg_quote_except($str, '\\*', '/');
Я переместил параметр разделителя в конец, чтобы он мог быть необязательным.