0

どうすればこのようなものを変換できますか:

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

これに:

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

基本的に、引用符で囲まれた括弧のみをエスケープしたいと思います。

編集

私は正規表現が初めてなので、これを試しました:

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

しかし、これは ( の最初の発生をエスケープするだけです。

編集2

おそらく、文字列でこれらの括弧が既にエスケープされている可能性があることを言及する必要があります。この場合、それらを再度エスケープしたくありません。

ちなみに、二重引用符と一重引用符の両方で機能する必要がありますが、そのうちの1つに機能する例がある限り、それができると思います.

4

5 に答える 5

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>=5.3用です。下位バージョン(> = 5)を使用している場合は、コールバックの無名関数を別の関数に置き換える必要があります。

于 2013-02-04T14:20:06.750 に答える
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);
于 2013-02-04T14:49:13.870 に答える
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)');
于 2013-02-04T14:27:04.570 に答える
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)
于 2013-02-04T14:41:44.713 に答える