はじめに
以前投稿した記事にていただいた編集リクエストで、気になったものがあったので調査した備忘録
メールアドレスの正規表現を例に、[]内でのエスケープすべき文字を調査しました
お品書きは下記の通り
- 問題となった正規表現
- []内でエスケープすべき文字たち
- 以上を踏まえたキレイ(?)な正規表現
- さいごに
問題となった正規表現
正規表現:https?://[\w!?/\+\-_~=;.,*&@#$%\(\)\'\[\]]+
編集リクエスト:*[]内の?, , $をエスケープする
これは、メールアドレスを判定するときに使用していた正規表現
このリクエストを受け、さっそく正規表現を修正してテストをした
編集リクエスト通り修正し、問題なく処理されることが分かったのですが、一つ疑問が浮上した
なんでエスケープしなくても動いたの????
ということでいろいろと調べた結果[]内では特定のメタ文字しか使われていないのではという考えに至った
[]内でエスケープすべきメタ文字たち
[]の正規表現は[]内にある文字(集合)のいずれかにマッチするという意味で
[abc]とした場合、aかbかcのいずれかにマッチ
であった
当然記号などの文字(集合)でも上記のことが言えて、
[a?.+]と入力した場合、aか?か.か+のいずれかにマッチ
となることはわかった
\wや\Sなどは一つ一つの要素が文字(集合)となるので心配ご無用
また、メタキャラクタではない英字(jやl)を使って
\j\l\wとした場合、jl(a ~ z)にマッチ
という意味になる
つまり、特別な意味がない文字にエスケープをしてもしなくても普通の文字や記号なのである
では全部の文字をエスケープしなくていいかというと、以下のメタ文字たちは例外である
範囲を意味するハイフン(-)
[]内でのみエスケープをする記号
[a-z]
としたとき、「aからz(小文字アルファベットのいずれかにマッチしたとき」を意味するため、ハイフン(-)を文字として使用したい場合はエスケープが必要
補集合を意味するキャップ(^)
[^ABC]
としたとき、「A, B, C ではないものにマッチしたとき」を意味するため、キャップ(^)を文字として使用したい場合はエスケープが必要
エスケープを意味するバックスラッシュ(\)
バックスラッシュはエスケープを意味するため、文字として使用したい場合、バックスラッシュを二回( \\
)入力する必要がある
[] の終了を意味する大かっこ閉じ(])
[ABC]]
と入力した際、最初(5文字目)の大かっこ閉じ(])で閉じてしまうため、「(A or B or C)]にマッチ」という正規表現になってしまう
そのため、]はエスケープが必要
以上を踏まえたキレイ(?)な正規表現
[]内で使用されるメタ文字だけエスケープする正規表現と、
メタ文字として使われる文字全てエスケープする正規表現を記載しておく
やっぱり中途半端よりも統一したほうがいいですからね…
- 必要なものだけエスケープ
https?://[\w!?/+\-_~=;.,*&@#$%()'[\]]+
- メタ文字は全部エスケープ
https?://[\w!\?/\+\-_~=;\.,\*&@#\$%\(\)'\[\]]+
個人的には1の方が見やすいので好みですが、慣れるまでは2を使っていこうかな…
さいごに
今回いただいた編集リクエストで、あいまいにしていたところを調べられました
ありがとうございました<(_ _ )>
自分では見えていなかった(見てなかった部分も…?)ところを再度調べてみました
また、この考えは違うなどありましたらご教授いただけると光栄です( ^_^)/