web-dev-qa-db-ja.com

preg_replace()e修飾子をpreg_replace_callbackに置き換えます

正規表現がひどいです。私はこれを置き換えようとしています:

public static function camelize($Word) {
   return preg_replace('/(^|_)([a-z])/e', 'strtoupper("\\2")', $Word);
}

匿名関数を使用したpreg_replace_callbackを使用します。 \\ 2が何をしているのかわかりません。または、そのことについては、preg_replace_callbackの動作方法を正確に説明します。

これを達成するための正しいコードは何ですか?

82
Casey

正規表現では、(brackets);を使用して、一致した文字列の一部を「キャプチャ」できます。この場合、一致の(^|_)および([a-z])部分をキャプチャしています。これらには1から始まる番号が付けられているため、後方参照1と2があります。一致0は一致した文字列全体です。

/e修飾子は置換文字列を取り、バックスラッシュの後に数字(例:\1)を適切な後方参照で置き換えます-しかし、文字列の中にいるので、バックスラッシュをエスケープする必要があります。 '\\1'を取得します。次に、(事実上)evalを実行して、結果の文字列をPHPコードであるかのように実行します(これは、evalを安全でない方法で使用するのが簡単なため、廃止された理由です) )。

代わりにpreg_replace_callback関数はコールバック関数を受け取り、一致する後方参照を含む配列を渡します。したがって、'\\1'を記述した場所では、代わりにそのパラメーターの要素1にアクセスします。 function($matches) { ... }という形式の匿名関数がある場合、最初の後方参照はその関数内の$matches[1]です。

したがって、/e引数は

'do_stuff(\\1) . "and" . do_stuff(\\2)'

のコールバックになる可能性があります

function($m) { return do_stuff($m[1]) . "and" . do_stuff($m[2]); }

またはあなたの場合

'strtoupper("\\2")'

になる可能性があります

function($m) { return strtoupper($m[2]); }

$m$matchesは魔法の名前ではなく、コールバック関数を宣言するときに指定したパラメーター名にすぎないことに注意してください。また、匿名関数を渡す必要はありません。文字列としての関数名、またはarray($object, $method)PHPのコールバックと同様 などの形式の関数名を渡すことができます。

function stuffy_callback($things) {
    return do_stuff($things[1]) . "and" . do_stuff($things[2]);
}
$foo = preg_replace_callback('/([a-z]+) and ([a-z]+)/', 'stuffy_callback', 'fish and chips');

他の関数と同様に、デフォルトではコールバックの外側の変数(周囲のスコープから)にアクセスできません。匿名関数を使用する場合、useキーワードを使用して、アクセスする必要がある変数をインポートできます PHPマニュアルで説明されているように 。例えば古い引数が

'do_stuff(\\1, $foo)'

新しいコールバックは次のようになります

function($m) use ($foo) { return do_stuff($m[1], $foo); }

落とし穴

  • preg_replace_callbackの使用はではなく正規表現の/e修飾子なので、「パターン」引数からそのフラグを削除する必要があります。したがって、/blah(.*)blah/meiのようなパターンは/blah(.*)blah/miになります。
  • /e修飾子は引数でaddslashes()のバリアントを内部的に使用したため、一部の置換ではstripslashes()を使用して削除しました。ほとんどの場合、新しいコールバックからstripslashesへの呼び出しを削除することをお勧めします。
72
IMSoP

フラグe(または一般的にeval)を使用しないでください。

T-Regx library を使用することもできます

pattern('(^|_)([a-z])')->replace($Word)->by()->group(2)->callback('strtoupper');
0
Danon