[解決済み] preg_replace() の e 修飾子を preg_replace_callback に置き換える。
質問
私は正規表現が苦手です。これを置き換えようとしています。
public static function camelize($word) {
return preg_replace('/(^|_)([a-z])/e', 'strtoupper("\\2")', $word);
}
のように、preg_replace_callbackを無名関数に置き換えています。この関数が何をやっているのか分からない。というか、preg_replace_callbackがどのように動作するのか正確に理解していない。
これを達成するための正しいコードは何でしょうか?
どのように解決するのですか?
正規表現では、マッチした文字列の一部を、"capt".
(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
という修飾子がつくので、そのフラグを "pattern" 引数から削除する必要があります。そのため、次のようなパターンが/blah(.*)blah/mei
は次のようになります。/blah(.*)blah/mi
. -
は
/e
モディファイアはaddslashes()
を使うので、いくつかの置き換えでは、引数でstripslashes()
を使って削除することもできます。stripslashes
への呼び出しを削除したいでしょう。
関連
-
[解決済み】予期せぬ例外。SQLSTATE[HY000] [1045] Access denied for user ****@'localhost' (using password: YES)
-
[解決済み】DateTimeクラスのオブジェクトを文字列に変換できない
-
[解決済み] [Solved] Fatal error: 非オブジェクトのメンバ関数fetch_assoc()の呼び出し [重複]。
-
[解決済み】Wordpressの子テーマのstyle.cssが効かない。
-
[解決済み] mysql_field_nameを新しいmysqliに変更します。
-
[解決済み] Microsoft Excelで正規表現(Regex)をセル内とループの両方で使用する方法
-
[解決済み] Sublime Text 2での正規表現検索置換
-
[解決済み】PHPの'foreach'は実際どのように動作するのですか?
-
[解決済み] リファレンス - このシンボルはPHPで何を意味するのですか?
-
[解決済み】MySQLで正規表現による置換を行うには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】SQLSTATE[42000]: 構文エラーまたはアクセス違反が発生しました。1064 SQL 構文にエラーがあります - PHP - PDO [重複]。
-
[解決済み】「初期通信パケットの読み込み」でMySQLサーバーに接続できなくなり、システムエラーになる。0
-
[解決済み】XAMPPエラー: www.example.com:443:0 サーバー証明書に、サーバー名と一致するIDが含まれていません。
-
[解決済み】Laravel 5.2 Storage::makeDirectory($dir) でディレクトリが作成されない。
-
[解決済み】PHP フェイタルエラー。未定義の関数mssql_connect()をコールしています。
-
[解決済み】既に開始されているPHPセッション【重複あり
-
[解決済み】SSLピア証明書またはSSHリモートキーがOKでなかった
-
[解決済み】Wordpressの子テーマのstyle.cssが効かない。
-
[解決済み】MySQLのカラム数が1行目の値数と一致しない【非公開
-
[解決済み】警告: file_get_contents(): https:// ラッパーがサーバー構成ですべて無効になっています。