正規表現とは

電話帳や郵便番号簿から目的のデータを探すときはどうするだろう。 おそらく先頭から1〜2文字(イニシャル)を利用して、検索ボタンなり索引を使っ て探すだろう。誰が登録されているか覚えていれば良いが、未知のものから探す のはたいへんである。また、データの先頭の文字を忘れていたり、 「サトウ」なのか「サイトウ」なのかとか、 「イカラシ」なのか「イガラシ」なのかなど、途中があやふやだったりすると 検索ではできない。

なにかを検索するときに、そのデータに含まれている文字列のパターンを 汎用的に指定する方法がある。そのうち、もっとも一般的であるものが 正規表現である。

正規表現の例

たとえば、「サトウ」と「サイトウ」どちらかを探したい場合、 正規表現では次のように検索パターンを書く。

サイ?トウ

こうすると、"サトウ" または "サイトウ" 両方にマッチするようになる。 特別な文字 ? を指定すると、「その直前の文字があっても無くても いい」という指定になる。また、別の特別な文字 [ ] を使っても、 同様の指定ができる。たとえば、

イ[カガ]ラシ

とすると、"イカラシ" でも "イガラシ" でもマッチするようになる。 特別な文字 [ ] の中に何文字か文字を列挙すると、 その中のどれかの文字が来ればいい、という指定になる。

上記の正規表現の例は特殊な文字の働きを分かりやすくために最も単純に書 いたものであり、実際にRubyプログラムに正規表現を書くときはそのままでは 使えないので注意すること。

egrepコマンドによる正規表現の実験

実際に名簿のようなデータを作って、正規表現で検索する練習をしてみよう。 最初に検索のデータとなるファイルを作っておこう。以下のような名簿データファ イル、meibo.txt を作成しよう。

サトウ ムネユキ SATOH Muneyuki	さとう胸幸  青葉台
コウエキ タロウ KOEKI Taro	公益太郎    酒田
イイモリ ハナコ IIMORI Hanako	飯森花子    飯森山
サイトウ テツヤ SAITOH Tetsuya	斎藤徹夜    白夜の国

データファイル作成時の注意

実際に検索してみよう。本来は漢字でパターンを指定したいところだが、漢 字を指定する前に覚えなければ行けないことが色々あって面倒なので、この実験 ではローマ字でパターンを指定しよう。Unixには正規表現を使ってファイルから 特定の行を検索してくれるものとして egrep というコマンドが ある。egrep コマンドは

% egrep 正規表現パターン [ファイル群…]

のように起動し、0個以上の複数のファイルから「正規表現パターン」にマッ チする行だけを選んで出力してくれる。ファイルを0個指定すると、 標準入力から読み込んだデータから検索する。

標準入力/標準出力に関してはとても大事な概念なので Unixひとめぐりページを 良く読んでおくこと。

まずは検索してみよう。最初は、

どちらかを含む行を全部選んでみよう。この場合、大文字の I があっても無 くても良いので、正規表現パターンは "SAI?TOH" となる。

% egrep "SAI?TOH" meibo.txt

正規表現のパターンを "" でくくっているのは、途中にある ? 記号をファイル名マッチだと思われないようにするためである。 このようにコマンドラインで正規表現パターンを指定するときは、パターンを "" または '' で必ず括ること。

実行結果は次のようになるだろう。

% egrep "SAI?TOH" meibo.txt
サトウ ムネユキ SATOH Muneyuki  さとう胸幸  青葉台
サイトウ テツヤ SAITOH Tetsuya  斎藤徹夜    白夜の国

もう少し欲張って、楽になるように検索パターンを考えよう。 パターン指定にいちいち大文字を打つのは面倒だし、もしかしたらデータファイ ルの方で Satoh と書いてしまう場合もあるので、大文字でも小文字でもどちら でもマッチするようにしてみよう。検索のときに大文字小文字を区別しないため には egrep コマンドに -i オプションを指定すれば 良い。

% egrep -i "sai?toh" meibo.txt
サトウ ムネユキ SATOH Muneyuki  さとう胸幸  青葉台
サイトウ テツヤ SAITOH Tetsuya  斎藤徹夜    白夜の国

Rubyで使う正規表現

Rubyでは正規表現は / / で括って指定する。たとえば、 直前の egrep の例で指定した正規表現 "sai?toh" はRubyでは、

/sai?toh/

と表記する。これに注意して、

指定したファイルから sai?toh というパターンを検索する

Rubyプログラム saito.rb を作成すると次のようになる。

#!/usr/koeki/bin/ruby

while line=gets
  if /sai?toh/i =~ line
    print line
  end
end

まずは、実際に実行してみよう。egrep コマンドと同様 検索したいファイルを引数として与えよう(検索パターンはRubyプログラム内に 記述してあるのでコマンドラインからは指定しなくて良い)。

% chmod +x saito.rb
% ./saito.rb meibo.txt
サトウ ムネユキ SATOH Muneyuki  さとう胸幸  青葉台
サイトウ テツヤ SAITOH Tetsuya  斎藤徹夜    白夜の国

プログラム(本体部分)の内容を一行ずつ見ていこう。

  1. while line=gets

    gets はこれまで使ったことのあるメソッドである。こ れまでは、「キーボードから一行入力してその内容を文字列で返す」とい う説明をしていたが、必ずしもキーボードから入力するとは限らない。 Rubyプログラム実行時に何かのファイルを引数として指定するとそのファ イルの中味を順次読むようになる。Rubyプログラムに何も指定しないとキー ボードから一行読むことになる。

    今回の場合 ./saito.rb meibo.txt と起動した。引数と してmeibo.txt を指定したので、gets メソッ ドは、meibo.txt ファイルを1行ずつ読みこむ。つまり、一 回目の line=gets

    line="サトウ ムネユキ SATOH Muneyuki さとう胸幸 青葉台\n"

    となり、二回目の gets

    line="コウエキ タロウ KOEKI Taro 公益太郎 酒田\n"

    となる(\nは改行コード)。4行あるので、 while line=gets は4回くり返すことになる。 gets はこれ以上読むデータが無くなると false を返し、while ループは終了する。

  2. if /sai?toh/i =~ line

    このifで、読みこんだ行が正規表現にマッチしているか の判定を行なう。「正規表現にマッチしているか?」を意味する条件式は

    正規表現 =~ 文字列

    のように書く。/sai?toh/i は、Rubyによる正規表現の 指定である。後の / の直後にある i は 「大文字小文字を区別しない」という意味を付加する働きを持つ。つまり、 egrep コマンドの -i オプションは、Rubyで は、正規表現の直後に i をつけることになる。

    正規表現の後ろの =~ は、「正規表現がマッチすれば…」 という比較演算子である。逆に「マッチしなければ」を意味する演算子は !~ であり、これも覚えておくと良い。。

    =~ の右辺に指定した「文字列」が正規表現の比較対象 となる文字列である。

  3. print line

    line 変数にはデータファイルから読み込んだ行が入っ ているので、それを出力する。もちろん、一つ上の行にif があるので、正規表現にマッチした場合だけ該当行が出力される。

  4. end

    ifに対応するend

  5. end

    whileに対応するend


本日の目次