* U K I Y A H O N P O *
Nel mezzo del cammin di nostra vita mi ritrovai per una selva oscura,
che la diritta via era smarrita.
リロード   新規 下位ページ作成 編集 凍結 差分 添付 コピー 名前変更   ホーム 一覧 検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS
浮子屋商店もよろしく。

正規表現講座/7 の変更点


TITLE:間違いだらけの正規表現講座 level 7

#contents
#contentsx

* れっつ練習! [#vdcb7bcb]

さて、駆け足でやってきましたが、第6回までの説明で、正規表現での検索の基本の部分は押さえたことになります。

次回からは、正規表現の真骨頂、正規表現を使った置換のやりかたを見ていきますが、
ここらで一旦おさらいを兼ねて、検索の練習をしてみましょう。

* おさらい [#baac8c4b]

まずは、今まで出てきたメタ文字をおさらいしましょう。

|メタ文字|意味|出てきた回|h
|.|任意の1文字にマッチ|[[第1回>正規表現講座/1]]|
|[abc]|[]内のどれか1文字にマッチ|[[第1回>正規表現講座/2]]|
|[a-z]|[]内のa~zにマッチ|[[第2回>正規表現講座/2]]|
|[^abc]|[]内以外の任意の1文字にマッチ|[[第2回>正規表現講座/2]]|
|*|直前の正規表現の、0回以上の繰り返し|[[第3回>正規表現講座/3]]|
|+|直前の正規表現の、1回以上の繰り返し|[[第3回>正規表現講座/3]]|
|?|直前の正規表現の、0回もしくは1回の繰り返し|[[第3回>正規表現講座/3]]|
|()|()内の正規表現を、まとめて1つの正規表現として扱う|[[第4回>正規表現講座/4]]|
|\t|タブ記号|[[第5回>正規表現講座/5]]|
|\r|改行記号 0D|[[第5回>正規表現講座/5]]|
|\n|改行記号 0A|[[第5回>正規表現講座/5]]|
|\|直後の記号をエスケープする|[[第5回>正規表現講座/5]]|
|^|先頭にマッチ|[[第6回>正規表現講座/6]]|
|$|末尾にマッチ|[[第6回>正規表現講座/6]]|

* レッツチャレンジ [#ted1c7d3]

では、例題です。試しに、HTMLのようなものの検索をしてみましょう。

正規表現テスターを立ち上げ、以下の文章をコピペして、チャレンジしてみてください。~
上手く行ったら、自分の使っているエディタに正規表現の機能があるかどうか調べ、
そのエディタでも試してみましょう。

なお、正規表現テスターでは、

-シングルラインモードON/OFF:『「.」が改行にもマッチする』(チェックでON)
-マルチラインモードON/OFF:『「^$」が各行毎にマッチする』(チェックでON)
-改行記号は \n 

となっています。

* 例題 [#ra4e6e46]

 #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とか)にマッチする正規表現を書け((ヒント:「.」はメタ文字です!))
- 「<a href="~">」の部分にマッチする正規表現を書け((ヒント:途中の空白が何文字か決まっていませんね))
- へも、の繰り返しで出来ている部分にマッチする正規表現を書け((ヒント:「へも」を単位とした繰り返しです))
- タグ(<と>で囲まれたもの)に全てマッチする正規表現を書け((ヒント:シングルラインモードは?))
- コメントっぽい行(最初の2行)にマッチする正規表現を書け((ヒント:行の頭が#で始まっていますね))
- 行内で完結しているリンク(<aで始まり/a>で終わる)にマッチする正規表現を書け((ヒント:シングルラインモードは?))
- 全てのリンクにマッチする正規表現を書け((ヒント:最後のリンクはどうしましょう))

* 欲張りなマッチと欲張りでないマッチ [#h8c05c43]

さて、最後の問題が厄介だったのではないでしょうか。

単純に「<a.*/a>」などとすると、最後のリンクは改行が混じっているので
マッチできませんね。

仕方ないので、シングルラインモード(「.」が改行にもマッチする)を
チェックして試してみると、今度は、4つのリンクが全部いっぺんにマッチして
しまった筈です。

これは、第3回でちらっと述べた、「最長一致の法則」、別名「欲張りなマッチ」
という仕様が関係しています。

「.*」は、マッチできる限り最長の文字列にマッチしようとします。

「.」が改行にマッチしない場合(シングルラインモードOFF)であれば、
「.*」は改行のところで有効範囲が切れるのですが、
「.」が改行にマッチするようにすると、
何行も何行も延々とマッチし続けてしまうのですね。

つまり、~
''『「<a」で始まって、改行を含む何文字かがあって、「/a>」で終わる最長の文字列』''~
を探してしまうわけで、途中に「<a」や「/a>」が含まれていても、
それは「.*」の一部分と考えられてしまうわけです。

このような場合に使うのが、「最短一致」です。

&color(Red){「*」「+」の後に「?」をつけると、その場合だけ、「*」「+」は、「可能な限り最短の文字列にマッチ」するようになります。};

シングルラインモードONの状態で、「<a.*?/a>」で検索して試してみてください。
今度は上手く行く筈です。

この場合、~
''『「<a」で始まって、改行を含む何文字かがあって、「/a>」で終わる最短の文字列』''~
を探すので、このような動作になります。

というわけで、メタ文字の一覧に追加です。~
こればかりは、実際に例題をやって悩んでみないと存在意味がわからないので、~
最後にもってきたのでした。

|メタ文字|意味|h
|*?|直前の正規表現の、0回以上の繰り返し(最短一致)|
|+?|直前の正規表現の、1回以上の繰り返し(最短一致)|

なお、「*」「+」だけでなく、量指定子と呼ばれる、繰り返しを指定する
メタ文字であれば、その後ろに「?」をつけることにより、最短一致に
することができます。

* ちょっと脱線 [#wa94b11e]

さて、本文中、いきなり「欲張り」とか言い出してふざけてると思ったのではないでしょうか。~
が、実は「欲張りなマッチ」「greedy match」という、正規表現上の専門用語なのです。~
他にも、「強欲なマッチ」「possessive match」なんてのもあります。

コンピュータの専門用語、特にUNIX系の用語って、プロセスを殺したり(kill)、
プロセスがゾンビ(zombie process)になったり、OSがあわてふためいたり(panic)、
茶目っ気のあるというか、コンピュータを擬人化したものが多いですね。

プログラムをしていると、そういう言葉を使うのは良く分かります。~
プログラミングというのは、無意識にコンピュータやプログラムの「気持ち」を想像して、~
「プログラムの立場に立って」ものを考えるからでしょうか。

開発の現場にいると、

 この子があっちのサーバにリクエストを投げます。もしサーバがダンマリだったり
 死んでたりしたら、仕方ないのでDBを見に行って別のサーバに投げなおします。

なんて発言は日常茶飯事、だれも気にせず使っていますが、

 このプロセスがあっちのサーバにリクエストを送信します。もしサーバがレスポンスを
 返さなかったり、サーバが起動していなかったりしたら、データベースを検索して、
 別のサーバに送信しなおします。

というのが正しい日本語ですよね。

* ご指摘などはこちらへ [#kedca7c3]

#comment