【サルにもわかる正規表現入門】
1.正規表現とはなにか?
端的に言えば、「いくつかの文字列を一つの形式で表現するための表現方法」です。
では、なぜこの表現方法が有名なのかといえば、この表現方法を利用すれば、たくさんの文章の中から容易に見つけたい文字列を検索することができるためです。
この形式を使えば、以下のようなコギャルの会話にもついていけます(^_^)
「Windows ってあって…WINDOWSかもしんないしぃ、次にスペースが入ってるかもしんないしぃ、入ってないかもしんないし、後にやっぱ98 が付くってゆーかー、もしかすると 95 が付いてもいいかなぁって感じでぇ…」
これ以上続けるとこちらがキレてしまいそうなのでこのあたりにしておきますが…これは、正規表現で書くと…
W(indows|INDOWS) ?9[85]
って感じで一行で書けちゃうっていうかぁ…あ、つい、口調が移ってしまった(^_^;)…書けるのであります。
慣れればこれほど便利な方法はありませんが、ただ、ちょっと難しそうに見えます。そこでこの入門書の出番ということになります(^_^)
2.正規表現で使用する特殊文字
正規表現とは、前に説明しましたように、「いくつかの文字列を一つの形式で表現するための表現方法」です。その「一つの形式で表現するため」に、いくつかのある文字に対して特別な意味を与えています。
以下に述べる文字がその役割を担っています。すべて半角です。
|
これらの特殊文字を正規表現では、「メタ文字」と呼んでいます。「メタ」というのは、「超」と言う意味で、あの「チョーむかつく」の「チョー」と同じ意味です。普通の文字以上の意味を含んでいるという意味になるかと思います。
しかしながら、これらのメタ文字は文字としてもよく見受けられる文字ですよね。そうです、そこに問題があります。
例えば、私たちはおおっぴらにすることをはばかって以下のような書き方をしたりします。
「俺はB*** G****が大嫌いだ!」
これだと「俺はBeer Gardenが大嫌いだ!」という酒の嫌いな方の意見になったりします(^_^)が(ひとつ文字が足りないことはおいといて(^_^;;)
そこで、この行を検索しようとして、検索する文字列にそのまま
「俺はB*** G****が大嫌いだ!」
と入力したりすると、永久にこの行は検索できません(^_;)
もうおわかりかと思いますが、この行に含まれている *というメタ文字が*そのものを意味していないからなのです。私なんかもよくそれを忘れていて、「なぜ誤検索するんだろう」と悩むことがよくあります。
ですので、このメタ文字を単なる普通の文字として検索したい場合は、それらメタ文字の前に、\を付加しなければなりません。下記の例のように。
|
なお、\ 自体は、\\と書きます。
3.メタ文字の種類
では、メタ文字を種類ごとに解説していきます。以下、具体例で示していきます。わかりやすくするため大きな文字を使用していますが、メタ文字はすべて半角です。
(1)とにかくなんでもいい1文字 .
半角の .を使用すると、とにかくなんでもいい1文字を表現することができます。
正 規 表 現 | 私は.です |
検索できる文字列の例 |
|
つまり、下線の文字の部分がなんでもいいことになります。
「正規表現」の書きかたひとつで、「検索できる文字列の例」がすべて検索できるということです。
さらに、これを応用してみます。
正 規 表 現 | 私は...が.. |
検索できる文字列の例 |
|
…と、 .を繋げることでいろんな表現が可能になるのがおわかりになるでしょう。
しかし、 . そのものを検索したい場合がありますね。例えば、TEST.LOG を検索したい場合などですね。この場合は、
正 規 表 現 | TEST\.LOG |
検索できる文字列の例 | TEST.LOG |
つまり、.の前に\を付けることで、.を正規表現の.ではなくて、単なるひとつの文字のとしての.という意味に変えることができるのです。
(2)行の先頭と最後 ^$
行の先頭や最後にのみ存在する文字列を検索したい場合があります。
例1 |
|
例2 | |
例3 |
|
これらの例に対して、
正 規 表 現 |
|
によって検索すると、合致するのは例2だけとなります。
つまり、半角の ^ は、行の先頭を意味します。ですから、この「正規表現」の場合は、行の先頭に存在する「ありがとう」の文字しか検索しないのです。
逆に、
正 規 表 現 | |
の場合は、 $ が行の終わりを意味します。この例では行の終わりにある「ありがとう」しか検索しません。ですので、合致するのは、例3だけとなります。
また、以下のようにこの両方を同時に指定した場合、
正 規 表 現 |
|
とすると、「ありがとう」の文字だけのある行に合致します。
なお、行頭にある普通の文字の ^ 、行末にある $ を検索したい場合は、それぞれ
正 規 表 現 |
|
正 規 表 現 |
|
として下さい。
これからもおわかりのように、^は正規表現の先頭、$は終端のものしかメタ文字として認識されません。
(3)同じ文字の繰り返し*+?
同じ文字の繰り返しを表す正規表現は、 * + ? の3つあります。
正 規 表 現 | おー*い |
検索できる文字列の例 |
|
この例からもわかりますように、 * は、* の直前の文字がないか、直前の文字が1個以上連続するという意味になります。
ここで注意して頂きたいのですが、ファイル名を指定する時のワイルドカードで使用される * とは、意味が異なります。
ワイルドカードの * では、「おー*い」は、
おーい おーーい おーーーーい
などと同等の意味になります。
すなわち、* は直前の文字がなんであろうと関係なく、「ー」の後の文字がまったくなくて「い」が来ているか、どんな文字でもいいから、1個以上の文字が「ー」の後に続いて、最後に「い」が来ているかが問題になります。
正 規 表 現 | おー+い |
検索できる文字列の例 |
|
+ の場合は、* とは違い、最低でも1個は + の直前の文字がないといけません。
後は、それが連続するという意味になります。
正 規 表 現 | おー?い |
検索できる文字列の例 |
|
? の場合は、直前の文字がまったくないか、1つだけあるという意味です。
これはどういう場合に便利かと言いますと、
正 規 表 現 |
|
検索できる文字列の例 |
|
と言う風に、単数形と複数形のどちらでも合致させたい場合に利用できます。
正 規 表 現 | Windows ?98 |
検索できる文字列の例 |
|
と言う風に、スペースがあるかどうか不明の文字列を検索する場合にも利用できます。
* と + と ? は、少しずつ違うので、その違いを理解して下さい。
3.メタ文字の種類
(4)なんでもいい文字の連続 .*
さて、 * + ? の正規表現は、「(1)とにかくなんでもいい1文字」のところで説明しました、 . と併用することができます。
正 規 表 現 | 君が好き.*。 |
検索できる文字列の例 |
|
この例では、「君が好き」で始り、「。」で終わる文字列を検索しています。
. は、とにかくなんでもいい1文字の意味でしたね。そして、* は、* の直前の文字がないか、連続する場合でしたね。
そこで、 .* というのは、とにかくなんでもいい1文字がまったくないか、連続するかという意味になります。とにかくなんでもいい文字が連続すると言うのは、つまりは、いろんな文字の連続と言うことになります。
そこで、上の例の場合は、「君が好き」で始り、「。」までの文字列ということになる訳です。
言わば、これが、ワイルドカードで使用される * と同じ意味を持つ正規表現ということになります。
上記の「君が好き.*。」のような使用例は、何かの文字で始り何かの文字で終わる文字列を指定する時に有用です。
+ ? についても、それぞれ併用効果は違いますが、直前の文字が . ということでなんでもいい1文字ということになります。
それぞれ適用できる場面があるかと思いますので、考えてみて下さい(^_^)。
【.*はどこまで繋がるのか】
さて、ここでひとつ疑問が起きます。以下の例に対して、
例 |
|
以下の正規表現で検索すると、
正 規 表 現 | 楽.*ね |
合致するのは、「楽しいかもね」まででしょうか?それとも「楽しいかもね、そうかかもね」でしょうか?
正解は、「楽しいかもね、そうかもね」までです。
つまり、.*というのは、可能な限り合致するものまで繋がるのです。
従って、正規表現の最後に.*が来た場合は、行の最後まで合致することになります。
(4)いずれかの文字列 |
さて、今までの(1)~(4)までの正規表現は、1文字に対して機能するものばかりでした。
今度は、複数の連続する文字について適用される正規表現を見ていきます。
正 規 表 現 |
|
検索できる文字列の例 |
|
つまり、| で区切られた文字列のいずれかの文字列が存在した時に、正規表現に合致したことになります。
この | はいくらでも並べられますが、実際は、ソフトによっては溢れて落ちてしまうこともありますので、70文字ぐらいにとどめるのが無難でしょう。
(5)指定した文字のどれか [ ]
例1 |
|
例2 | |
例3 |
|
例4 |
|
これらの例に対して、
正 規 表 現 |
|
の場合は、合致するのは、例1、例2、例3です。例4は合致しません。
つまり、 [ ] で括られた中の文字は、その中のどれか1つに合致する訳です。
これが、もしも、「(1)とにかくなんでもいい1文字」のところで説明した半角の . を使用すると、
正 規 表 現 | 明日は. です |
ということになると、例1から例4までのすべてが合致します。
しかし、たとえば、すべての数字とか、すべてのアルファベットを指定したい時、
正 規 表 現 |
|
とか、
正 規 表 現 |
|
と書けなくもありませんが、これは非常に面倒ですね。
まあ、これだけならばいいですが、今度は全角のABCDE…も同時に指定したい場合には、もう表現のしようがありません。
でも、ご安心下さい。こんな場合に備えて、
正 規 表 現 |
|
正 規 表 現 |
|
というような書きかたもあります。
この中の、 [A-Z] と言うのは、A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Zの文字のどれかということになります。同じように、[0-9]は、0,1,2,3,4,5,6,7,8,9の文字のどれかということになります。
ですので、はじめの例では、Aで始り、2番目の文字が半角の大文字のアルファベットが来て、最後はCCCの文字が来るものということになります。同じように、その次の例では、Aで始り、2番目の文字が半角の数字が来て、最後はCCCの文字が来るものということになります。
これだと、非常に複雑なことも書けますね。
この書きかたは、連続して書けますので、
正 規 表 現 |
|
と書けば、Aで始り、次の文字が半角の大文字アルファベットか数字で、CCCで終わる文字列の検索ができる訳になります。
ところが、今度は逆に上記のはじめの例で言うと、第2番目の文字が半角のアルファベット以外を指定したい場合があります。
はい、これも実は書きかたがあります。
正 規 表 現 |
|
と書けば、Aで始り、2番目は半角アルファベット以外の文字で、最後はCCCというものを探してくれます。
これもまた、連続して書けますので、
正 規 表 現 |
|
とすれば、2番目の文字は、アルファベットと数字以外の文字ということになります。このように[ ]の中で ^ が使用された場合は、行の先頭を表す ^ とは意味が異なりますので注意して下さい。
さて、今までの例は半角でしたが、全角の場合はどうでしょうか?
正 規 表 現 | た[か-こ]こ |
検索できる文字列の例 |
|
この例では、2文字目は、「か き く け こ」の内のいずれかの文字が該当するはずです。
しかし、現実には、「たがこ」にも「たぎこ」には合致します。これはどういうことでしょうか?
[か-こ]というのは、日本語の50音の並びに基づいているのではないということなのです。それは、JIS漢字コード表の並びに基づいているのです。
JIS漢字コード表の並びを見てみますと、下記のようになっています。
か行のJIS漢字コード表 |
|
つまり、[か-こ]の文字というのは、単純に か き く け こ の文字ではなくて、上記の文字の中のどれかということになるわけです。
ですから、半角の場合はあまり問題になることはありませんが、全角の並びの場合は、必ずしも50音の順にはなってはいないということに注意して下さい。
できましたら、[か-こ]のような使用をされる場合は、JIS漢字コード表を参照されることをお勧めします。
ちなみに、[弌-熙]は第2水準の漢字のいずれかという意味です。
ここでちょっと注意すべき事があります。それは、[ ]の中ではメタ文字は普通の文字として認識されると言うことです。従って、メタ文字を普通の文字として探させたい場合でも、わざわざ直前に \ を付ける必要はありません。ただし、] と \ につきましては例外です。以下に例を示しますと…
正 規 表 現 | [.*] |
検索できる文字列の例 | . か * のいずれかの文字。いずれの文字もメタ文字ではない。 |
正 規 表 現 |
|
検索できる文字列の例 |
|
^ は文字として認識させたい場合は、必ず[ ]の中の2番目以降に記載のこと。先頭に書くと、上記で説明したように^に続く文字を否定する意味のメタ文字になってしまいます。
正 規 表 現 |
|
検索できる文字列の例 |
|
このように [ ] の中の先頭文字 ^ に続く ^ はその文字自体を否定する。
正 規 表 現 |
|
検索できる文字列の例 |
|
正 規 表 現 |
|
検索できる文字列の例 |
|
このように[ ] の中で [ ] の文字を指定した場合は、[ はそのままで問題ないが、] の場合は \] と記述しないと誤検索します。
正 規 表 現 |
|
検索できる文字列の例 |
|
このように [ ] の中で \ の文字を指定した場合は、 \\ と記述しないと誤検索します。
正 規 表 現 |
|
検索できる文字列の例 |
|
これを逆にして
× 誤った正規表現 |
|
とは書かないで下さい。正確に検索できません。
3.メタ文字の種類
(6)グループ化 ( )
今までのメタ文字は主に1文字を対象としていました。しかし、まとめて数文字単位で処理できると便利な場合があります。こんな時に便利なのが ( ) です。( ) は ( ) の中をグループ化してくれます。この機能は非常に強力ですので、知っていて損はないと思います。
正 規 表 現 |
|
検索できる文字列の例 |
|
この例では、+ は直前の文字の1個以上の繰り返しなので、「検索できる文字列の例」のような文字列に合致します。
ところが、
正 規 表 現 |
|
検索できる文字列の例 |
|
この例では、( ) が使用されていますが、 + の直前の文字というのは、従来の1文字ではなく、( )に囲まれた部分の文字列になります。
つまり、「じゃ」の1回以上の繰り返しということになる訳です。
また、
正 規 表 現 |
|
検索できる文字列の例 |
|
この例では、「明日ぼく」「わたしは家に帰ります。」の文字列のいずれかが検索されますが、
正 規 表 現 |
|
検索できる文字列の例 |
|
この例では、まず、( ) の中を先に処理します。つまり、「ぼく」か「わたし」のいずれかの文字列を選びます。そして、( ) の外の文字列をそのまま連結します。すると「検索できる文字列の例」のように、2通りの文字列が検索できるのです。