替换PHP上引号内所有出现的char

时间:2013-02-04 14:07:40

标签: php regex escaping preg-replace

我怎么能转换这样的东西:

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

对此:

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

基本上,我想“仅”转义引号内的括号。

修改

我是Regex的新手,所以我尝试了这个:

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

但这只会逃避第一次出现(。

编辑2

也许我应该提一下,我的字符串可能已经转义了这些括号,在这种情况下,我不想再将它们转义。

顺便说一句,我需要它同时适用于双引号和单引号,但我认为只要我有一个工作示例,我就能做到这一点。

4 个答案:

答案 0 :(得分:1)

这应该用于单引号和双引号:

$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&gt; = 5.3。如果您的版本较低(&gt; = 5),则必须使用单独的函数替换回调中的匿名函数。

答案 1 :(得分:1)

您可以使用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)');

答案 2 :(得分:1)

给出字符串

$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)

答案 3 :(得分:1)

以下是使用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);