404 motivation not found | t_ishidaのブログ

1月/08

15

正規表現

正規表現って何?

えっと、アレです。ワイルドカードみたいな奴です。テキスト処理に便利な奴です。PHPで正規表現を使うための方法をメインに扱うので正規表現そのものについては、今回は簡単にしか触れません。本格的に正規表現を学びたい人は、grepや、sed、awkのソースを読むか、オライリーの詳説正規表現を読むか、次のURLを読んで下さい。

http://www.sixnine.net/regexp/index.html

内容の正誤については保障しません。

が、突っ込みは大歓迎です。

前書き

PHPでは正規表現が使えます。

と言うか、最近の言語は殆どが実装してます。

有名どころをパッと列挙すると、以下のようになります。

  • Perl
    • 正規表現のサポートと言うか、正規表現が言語になった感じ
    • /やる気/ and die ‘やる気が有るみたいです’;
  • VB
    • VBScript.RegExpをCreateObjectする事で使える
    • Dim re:Set re = CreateObject(”VBScript.RegExp”): re.pattern = “^Fuckin’VB$”
  • .NET
    • System.Text.RegExpで使える
  • JavaScript
    • Stringクラスに実装されている。
    • if ( “やる気なら有りません”.match( /^やる気/ ) ) {
  • Java
    • なんか素敵なオブジェクト指向で実装されていて、文字列マッチさせたいだけなのに、いくつインスタンス作るんだよ?って感じ。
  • Ruby
    • 多分、言語の指向上、オブジェクト指向で実装されている。組み込みのリテラルのように見えなくも無い
    • “やる気ならあります”.gsub(/あります/,”ありません”);

と、殆どが言語組み込みもしくは、オブジェクト指向による拡張と言う扱いなのに対して、PHPは関数で実装されています。

正規表現そのもの

そもそも正規表現とは、抽象的な文字列表現です。テキスト処理の世界では抽象的な文字列表現を使って、あいまい検索したり文字列の置換をしたりします。ちなみに、正規表現教では一致するをマッチすると言います。

"^a"    => 行頭に"a"がある文字列にマッチする
"^.a"   => 2文字目に"a"がある文字列にマッチする
"^.a+b" => 2文字目から"a"が1文字以上連続し、次に"b"がある文字列にマッチする

正規表現は、文字、メタ文字、量指定子、文字クラス、グループ化によって構成されます。

文字

普通の文字です。その文字そのものとマッチさせたい場合に使います。

t_ishida => t_ishidaが含まれる文字列とマッチする
メタ文字

メタ文字とは文字列表現を抽象的にする為の代替文字です。

メタ文字 意味
. 何でも良いから一文字とマッチ
\w 文字とマッチ
\d 数字とマッチ
\s 空白とマッチ
\t タブとマッチ
\n 改行とマッチ
^ 行頭とマッチ
$ 行末とマッチ
\D 数字以外とマッチ
\W 文字以外とマッチ
\S 空白以外とマッチ

a\d  => aの直後に数字がくる文字列とマッチする。
量指定子

量指定子とは、何文字それが続くよ。って言うのを表現する為に使います。

2008/04/03追記(無欲(最小マッチ)強欲について)

量指定 意味
* 0個以上、無限にある(強欲)
+ 1個以上、無限にある(強欲)
? 0個か1個
{x} x個ある
{x,y} x個からy個の間ある
*? 0個以上、無限にある(無欲)
+? 1個以上、無限にある(無欲)

\d{5,11} => 数字が5個以上、11個以内続く文字列とマッチする

http://d.hatena.ne.jp/t_ishida/20080222#1203696072(より転載)

<div id="test">
<p>aaaa</p>
<div id="test2">
aaaa
</div>
</div>

という値があるときに、id=”test2″のinnerHTMLを取得したい場合、

preg_match( '/<div id="test2">(.+)<\/div>/msi', $html, $tmp );

ってやると、$tmp[1]が、”aaaa</div>”になってしまう。これは”+”が「強欲なマッチ」だから。

なので、この場合は最小マッチを使うと良い。最小マッチは”+?”,”*?”となる。

preg_match( '/<div id="test2">(.+?)<\/div>/msi', $html, $tmp );

$tmp[1]は期待通りに、aaaが取得できる。

文字クラス

文字をまとめたモノです。大括弧で、まとめたい文字を囲むと出来上がりです。説明するより見たほうが早いと思うので、とりあえず書きます。

[aZx] => aか、Zか、xとマッチする

のように、マッチさせたい文字をまとめて記述させる事が出来ます。

[tsa]_ishida => t_ishida,s_ishida,a_ishida のいずれかとマッチする

否定文字クラスと言うのも有ります。文字クラスで指定した以外の文字1文字として機能します。文字クラスの大括弧の中のはじめの文字を”^”にします。

t[^at]_ishida => tの後に、aとt以外の文字が来て_ishidaと続く文字列とマッチする。
例えば、
tb_ishidaとか、tc_ishidaとかはマッチしますが、
ta_ishida、tt_ishidaはマッチしません。

グループ化

()で囲む事によって、その部分の正規表現をグループ化する事が出来ます。グループ化する事によって量の指定をしたり、後方参照したり、色々出来ます。

t_(ishid[aA])?takeshi => "t_" + ishidaまたはishidA、その部分が存在しない + "takeshi"とマッチする

グループ化の内部では、論理和を使用する事が出来ます。論理和は”|”で表現します。

t_(ishida|toguchi) => t_ishidaまたは、t_toguchiとマッチします。

後方参照とはグループ化に部分とマッチした部分を後で使えると言うものです。分かり易いので、Perlを例にしてみると、

/^[^']*sql ?= ? sql & "([^"]+)"/ and print $1 while <>;

例は、sql = sql & と続いて、”に囲まれた範囲を後方参照して、置換して出力しています。

つまり、VBのソースコードからsql文字列だけを抽出して出力していると考えてください。

っと、ここまで書いてやる気が足りなくなったので続きは次回。

次回は実際に、今日やった「理屈」を実際に使って、

色々する方法、それからPHPで、それを使う方法を説明します。

Share and Enjoy:
  • Digg
  • del.icio.us
  • Google Bookmarks
  • Tumblr
  • email
  • Facebook
  • FriendFeed

RSS Feed

コメントはまだありません。

Leave a comment!

<< レイトン教授

PHPのオブジェクト指向 >>

Find it!

Theme Design by devolux.org

Tag Cloud