Заменить все вхождения char внутри кавычек на PHP

Как я мог преобразовать что-то вроде этого:

"hi (text here) and (other text)" come (again) 

К этому:

 "hi \(text here\) and \(other text\)" come (again) 

В принципе, я хочу избежать «только» круглых скобок, находящихся внутри кавычек.

РЕДАКТИРОВАТЬ

Я к новому в Regex, и поэтому я пробовал это:

 $params = preg_replace('/(\'[^\(]*)[\(]+/', '$1\\\($2', $string); 

Но это будет просто избежать первого появления (.

EDIT 2

Может быть, я должен упомянуть, что моя строка может иметь эти скобки уже сбежала, и в этом случае я не хочу ускользать от них снова.

Кстати, мне нужно, чтобы он работал как для двойных, так и для одиночных кавычек, но я думаю, что могу это сделать, пока у меня есть рабочий пример для одного из них.

Это должно сделать это как для одиночных, так и для двойных кавычек:

 $str = '"hi \(text here)" and (other text) come \'(again)\''; $str = preg_replace_callback('`("|\').*?\1`', function ($matches) { return preg_replace('`(?<!\\\)[()]`', '\\\$0', $matches[0]); }, $str); echo $str; 

вывод

 "hi \(text here\)" and (other text) come '\(again\)' 

Это для PHP> = 5.3. Если у вас более низкая версия (> = 5), вы должны заменить анонимную функцию в обратном вызове отдельной функцией.

Вы можете использовать preg_replace_callback для этого;

 // outputs: hi \(text here\) and \(other text\) come (again) print preg_replace_callback('~"(.*?)"~', function($m) { return '"'. preg_replace('~([\(\)])~', '\\\$1', $m[1]) .'"'; }, '"hi (text here) and (other text)" come (again)'); 

Как насчет уже сбежавших строк;

 // outputs: hi \(text here\) and \(other text\) come (again) print preg_replace_callback('~"(.*?)"~', function($m) { return '"'. preg_replace('~(?:\\\?)([\(\)])~', '\\\$1', $m[1]) .'"'; }, '"hi \(text here\) and (other text)" come (again)'); 

Учитывая строку

 $str = '"hi (text here) and (other text)" come (again) "maybe (to)morrow?" (yes)'; 

Итерационный метод

  for ($i=$q=0,$res='' ; $i<strlen($str) ; $i++) { if ($str[$i] == '"') $q ^= 1; elseif ($q && ($str[$i]=='(' || $str[$i]==')')) $res .= '\\'; $res .= $str[$i]; } echo "$res\n"; 

Но если вы поклонник рекурсии

  function rec($i, $n, $q) { global $str; if ($i >= $n) return ''; $c = $str[$i]; if ($c == '"') $q ^= 1; elseif ($q && ($c == '(' || $c == ')')) $c = '\\' . $c; return $c . rec($i+1, $n, $q); } echo rec(0, strlen($str), 0) . "\n"; 

Результат:

 "hi \(text here\) and \(other text\)" come (again) "maybe \(to\)morrow?" (yes) 

Вот как вы можете сделать это с помощью функции preg_replace_callback() .

 $str = '"hi (text here) and (other text)" come (again)'; $escaped = preg_replace_callback('~(["\']).*?\1~','normalizeParens',$str); // my original suggestion was '~(?<=").*?(?=")~' and I had to change it // due to your 2nd edit in your question. But there's still a chance that // both single and double quotes might exist in your string. function normalizeParens($m) { return preg_replace('~(?<!\\\)[()]~','\\\$0',$m[0]); // replace parens without preceding backshashes } var_dump($str); var_dump($escaped);