
[PHP]preg_matchでバックスラッシュ「\」をマッチさせる。
こんにちは、SESエンジニアのつくねん。です。
最近開発した機能で
値にバックスラッシュが含まれる場合php側で全角に変換する。
という要件のものを実装しました。
まず、値に含まれるかの判断処理としてpreg_matchで一致したらと思い
$text = "バックスラッシュ\を含む";
preg_match("/\\/", $text);
としたところ
おや、、マッチしない。
ということでpreg_matchについて調べ直しました。
preg_matchの使い方
preg_match("検索する値(正規表現)", "検索対象文字列")
として、第二引数がマッチすれば1(int)を返す。
今回の場合は
検索する値(正規表現)にバックスラッシュを
検索対象文字列に値(入ってくる値)を入れれば良いはず。
特殊文字のエスケープ
正規表現での特殊文字はエスケープが必要。
バックスラッシュもその1つで「\」は「\\」とする必要がある。
あれ、おかしいな。
問題ないはずなのに、と思い再度preg_matchのphpマニュアルを見ます。
PHPマニュアルで確認
phpのマニュアルでpreg_matchを確認。
すると、User Contributed Notesに下記がありました。
Matching a backslash character can be confusing, because double escaping is needed in the pattern: first for PHP, second for the regex engine
Google翻訳で直訳すると
"バックスラッシュ文字の一致は、パターンで二重のエスケープが必要なため、混乱を招く可能性があります。
最初は PHP の場合、2 番目は正規表現エンジンの場合です。"
なるほど、php、正規表現で二重にエスケープが必要なのか。
下記に修正して動作確認をします。
$text = "バックスラッシュ\を含む";
preg_match("/\\\/", $text);
これで取得成功。
一応マニュアルでエスケープシーケンスに関して確認してみると
注意:
シングルクォートあるいはダブルクォートで囲まれた PHP の 文字列 の中では、バックスラッシュは特別な意味を表します。 そのため、正規表現 \\ を使用して \ とマッチさせたい場合は PHP のコード内では "\\\\" あるいは '\\\\' と記述する必要があります。
とありました。
なので正確には
$text = "バックスラッシュ\を含む";
preg_match("/\\\\/", $text);
になるらしいです。(なぜ「/\\\/」でも一致するのでしょうか??)
エスケープややこしいですね。。。
解決できてよかったですが、また忘れそうです。
一つずつ分解して覚えておこうと思います。