れっつ練習!
さて、駆け足でやってきましたが、第6回までの説明で、
正規表現での検索の基本の部分は押さえたことになります。
さて、駆け足でやってきましたが、第6回までの説明で、正規表現での検索の基本の部分は押さえたことになります。
次回からは、正規表現の真骨頂、正規表現を使った置換のやりかたを見ていきますが、
次回からは、正規表現の真骨頂、正規表現を使った置換のやりかたを見ていきますが、
ここらで一旦おさらいを兼ねて、検索の練習をしてみましょう。
おさらい
まずは、今まで出てきたメタ文字をおさらいしましょう。
[^abc] | []内以外の任意の1文字にマッチ | 第2回? |
? | 直前の正規表現の、0回もしくは1回の繰り返し | 第3回? |
() | ()内の正規表現を、まとめて1つの正規表現として扱う | 第4回? |
[^abc] | []内以外の任意の1文字にマッチ | 第2回 |
? | 直前の正規表現の、0回もしくは1回の繰り返し | 第3回 |
() | ()内の正規表現を、まとめて1つの正規表現として扱う | 第4回 |
例題
レッツチャレンジ
では、例題です。HTMLのようなもの。
では、例題です。試しに、HTMLのようなものの検索をしてみましょう。
正規表現テスターを立ち上げ、以下の文章をコピペして、チャレンジしてみてください。
上手く行ったら、自分の使っているエディタに正規表現の機能があるかどうか調べ、
上手く行ったら、自分の使っているエディタに正規表現の機能があるかどうか調べ、
そのエディタでも試してみましょう。
なお、正規表現テスターでは、
- シングルラインモードON/OFFは、『「.」が改行にもマッチする』(チェックでON)
- マルチラインモードON/OFFは、『「^$」が各行毎にマッチする』(チェックでON)
- シングルラインモードON/OFF:『「.」が改行にもマッチする』(チェックでON)
- マルチラインモードON/OFF:『「^$」が各行毎にマッチする』(チェックでON)
- 改行記号は \n
となっています。
例題
#HTMLのようなもの。
#これはコメントです。
<html>
<a href="01234.html">電話番号#1="012-3456-7890"</a>
<a href="56789.html">電話番号#2="090-0000-0000"</a>
<a href="kenokeno.html">へもへも</a>
<a href="kenokeno.html">へもへもへも</a>
<a href="mononoke.html">ものへも
</a>
</html>
- 電話番号(012-3456-7890とか)にマッチする正規表現を書け。
- 数字で出来たファイル名だけ(01234.htmlとか)にマッチする正規表現を書け*1
- 「<a href="~">」の部分にマッチする正規表現を書け*2
- へも、の繰り返しで出来ている部分にマッチする正規表現を書け*3
- タグ(<と>で囲まれたもの)に全てマッチする正規表現を書け*4
- コメントっぽい行(最初の2行)にマッチする正規表現を書け*5
- 行内で完結しているリンク(<aで始まり/a>で終わる)にマッチする正規表現を書け*6
- 全てのリンクにマッチする正規表現を書け*7
欲張りなマッチと欲張りでないマッチ
さて、最後の問題が厄介だったのではないでしょうか。
多分、単純に「<a.*/a>」などとすると、最後のリンクは改行が混じっているので
さて、最後の問題が厄介だったのではないでしょうか。
単純に「<a.*/a>」などとすると、最後のリンクは改行が混じっているので
マッチできませんね。
仕方ないので、シングルラインモード(「.」が改行にもマッチする)を
チェックして試してみると、今度は、4つのリンクが全部いっぺんにマッチして
仕方ないので、シングルラインモード(「.」が改行にもマッチする)を
チェックして試してみると、今度は、4つのリンクが全部いっぺんにマッチして
しまった筈です。
これは、第3回でちらっと述べた、「最長一致の法則」、別名「強欲なマッチ」
これは、第3回でちらっと述べた、「最長一致の法則」、別名「欲張りなマッチ」
という仕様が関係しています。
「.」は、マッチできる限り最長の文字列にマッチしようとします。
「.」が改行にマッチしない場合(シングルラインモードOFF)であれば、
「.*」は、マッチできる限り最長の文字列にマッチしようとします。
「.」が改行にマッチしない場合(シングルラインモードOFF)であれば、
「.*」は改行のところで有効範囲が切れるのですが、
「.」が改行にマッチするようにすると、
「.」が改行にマッチするようにすると、
何行も何行も延々とマッチし続けてしまうのですね。
つまり、『「<a」で始まって、改行を含む何文字かがあって、「/a>」で終わる』
最長の文字列を探してしまうわけで、途中に「<a」や「/a>」が含まれていても、
つまり、
『「<a」で始まって、改行を含む何文字かがあって、「/a>」で終わる最長の文字列』
を探してしまうわけで、途中に「<a」や「/a>」が含まれていても、
それは「.*」の一部分と考えられてしまうわけです。
このような場合に使うのが、「最短一致」です。
「*」「+」の後に「?」をつけると、その場合だけ、「*」「+」は、
「可能な限り最短の文字列にマッチ」するようになります。
「*」「+」の後に「?」をつけると、その場合だけ、「*」「+」は、「可能な限り最短の文字列にマッチ」するようになります。
シングルラインモードONの状態で、「<a.*?/a>」で検索して試してみてください。
シングルラインモードONの状態で、「<a.*?/a>」で検索して試してみてください。
今度は上手く行く筈です。
この場合、『「<a」で始まって、改行を含む何文字かがあって、「/a>」で終わる』
という最短の文字列を探すので、このような動作になります。
この場合、
『「<a」で始まって、改行を含む何文字かがあって、「/a>」で終わる最短の文字列』
を探すので、このような動作になります。
というわけで、メタ文字の一覧に追加です。
というわけで、メタ文字の一覧に追加です。
こればかりは、実際に例題をやって悩んでみないと存在意味がわからないので、
最後にもってきたのでした。
メタ文字 | 意味 |
*? | 直前の正規表現の、0回以上の繰り返し(最短一致) |
+? | 直前の正規表現の、1回以上の繰り返し(最短一致) |
なお、「*」「+」だけでなく、量指定子と呼ばれる、繰り返しを指定する
メタ文字であれば、その後ろに「?」をつけることにより、最短一致に
することができます。
ちょっと脱線
さて、本文中、いきなり「欲張り」とか言い出してふざけてると思ったのではないでしょうか。
が、実は「欲張りなマッチ」「greedy match」という、正規表現上の専門用語なのです。
他にも、「強欲なマッチ」「possessive match」なんてのもあります。
コンピュータの専門用語、特にUNIX系の用語って、プロセスを殺したり(kill)、
プロセスがゾンビ(zombie process)になったり、OSがあわてふためいたり(panic)、
茶目っ気のあるというか、コンピュータを擬人化したものが多いですね。
プログラムをしていると、そういう言葉を使うのは良く分かります。
プログラミングというのは、無意識にコンピュータやプログラムの「気持ち」を想像して、
「プログラムの立場に立って」ものを考えるからでしょうか。
開発の現場にいると、
この子があっちのサーバにリクエストを投げます。もしサーバがダンマリだったり
死んでたりしたら、仕方ないのでDBを見に行って別のサーバに投げなおします。
なんて発言は日常茶飯事、だれも気にせず使っていますが、
このプロセスがあっちのサーバにリクエストを送信します。もしサーバがレスポンスを
返さなかったり、サーバが起動していなかったりしたら、データベースを検索して、
別のサーバに送信しなおします。
というのが正しい日本語ですよね。
ご指摘などはこちらへ