(8)06/08の授業内容
- 正規表現とは
- 正規表現の例
- 正規表現の練習
- while line=gets
- if /sai?to/i = ~line
- print line
- end
- end
- カタカナで「ワタナベ」さんと「ワタベ」さんにマッチする正規表現はなにか
- アルファベットで3人のフジシマさんにマッチする正規表現はなにか
- 正規表現の指定方法
- 通常の文字によるマッチング
- 行頭と行末のマッチング
- マッチさせたい文字を範囲で指定する
- 任意の文字とのマッチング
- バックスラッシュを使ったパターン
- 繰り返し
- ()と繰り返し
- 選択
- 自分の興味があるもの(例:好きな野球選手とチーム,自動車の車種とメーカー,ジュースとメーカー,雑誌と出版社,小説と作家,競走馬と調教師,聖闘士と必殺技)について,1行に1データを書いて記述し,data.txtというファイル名で保存する.少なくとも10行以上作成すること
- 個人情報保護の保護の問題があるため,サークルの名簿等,個人情報が含まれているものをそのまま利用することは避けること
- kensaku.rbの正規表現の部分を様々に変更し,データファイルの中からマッチするデータを取り出し,レポートする
- なお,毎回正規表現を変更するためにプログラムを書き換えるのが面倒だと感じる人は,キーボードから正規表現を入力できるように変更しても良い.ただしこれを独学で行うのはかなり難しいので,興味のある人のみとする(まだ教えていないことを自分なりに勉強しないと作成できない)
- Subjectは「学籍番号-kadai6」とすること
- 本文の1行目ではまず名乗ること
- 2行目以降は下記の構成で記載すること
- 作成したdata.txtとその説明(何のデータなのか)
- 作成したプログラム(作成した人のみ)
- プログラムの各部の説明(作成した人のみ)
- 使用した正規表現と実行結果
- 感想
- emacsで新しいファイルを作成する場合は,C-x C-fを押し,ミニバッファにkensaku/kadai2.rbのようにファイル名を入力する
- ファイルの保存はC-x C-s
- 日本語入力のオンオフの切り替えはC-o
- emacsを起動する
- Escとxを押し,mewと入力しReturn(Escとxを押すことを,一般にM-xと表記します)%<--これでMewが起動します
- Mewを起動するとパスワードがたずねられるので入力しReturn
- 新着メールの確認およびパスワードを間違えた場合はiと入力しReturn
- メールを読む場合は,カーソルキー(矢印キー)で読みたいメールを選びReturn
- メールの新規作成はwと入力
- e-mailの本文にテキストファイルを読み込むには,新規送信メール画面の本文を記入するエリアにカーソルを移動し,Ctrl+x,iとすると,ミニバッファにInsert file: ~/と表示されるので,読み込みたいファイル名を入力する。
- プログラムの実行結果の貼り付けは,kterm上の出力結果部分をマウスで選択し,Mewの本文の貼り付け位置にカーソルを移動し,マウスの真ん中ボタンをクリックする
- メールの送信はC-c C-cと入力するか,もしくはメニューのsendアイコンをクリックする
- Mewを終了するにはqと入力
- emacsを終了する
電話帳で「ハーブプラス」というお店の電話番号を探すことを考えます.電話帳ではお店の名前が50音順に並んでいますから,「ハ」の所を見れば書いてあることがわかります.では「髪ing」という美容室の電話番号はどのようにして調べればよいでしょうか? この場合「カミイング」と読むかもしれませんし,「ハツイング」や「ヘアイング」かもしれません(答えは「カミング」のようです).こんな場合に先頭の文字は読み方はわからないけれど,「ing」がついているお店というような方法で調べることができれば便利です.
次に名簿から特定の人物を探す場合を考えてみましょう.英語の授業で作成した名簿で,名前はローマ字で書かれており,かつNaoya KANDAというように名前が先に書かれているとします.このような名簿から藤島さんの住所を探すことを考えてみましょう.藤島さんの名前はわからないので名字を手がかりに探さなければならないのですが,fujisima,fujishima,hujisima,hujishima,fuzishima,...のように沢山の表記方法がありすぐには見つけられそうにありません.「shima」もしくは「sima」という文字が使われている名字の人というような探し方ができれば便利です
電話で名乗られたときも同じようなことが考えられます.「ビデオの予約をしていたと思うけれど,返却されていますか」というような問い合わせがあったとします.携帯電話から電話しているようであり,電波状況が悪く何度名乗ってもらっても「...トウです」としか聞こえません.どうも「イトウ」か「ゴトウ」のようなのですが,どちらだかわかりません.こんな時,「(イまたはゴ)トウ」という名字の人という探し方ができれば便利です.「サトウ」と「サイトウ」の聞き分けが難しい場合には「サ(イ)トウ」という名字の人という探し方が必要になるかもしれません
何かを検索するときに,そのデータに含まれる文字列の一部やパターンを利用することがあります.このパターンを表現するために使われるのが正規表現です
「FUJISHIMA」と「FUJISIMA」どちらかを探したい場合,正規表現では次のように検索パターンを書きます
FUJISH?IMA
?は直前のHはあってもなくてもよいという指定です.これで「FUJISHIMA」と「FUJISIMA」のどちらでもマッチするようになります.?以外にも[]を使って表現することもあります
スガ[ハワ]ラ
こうすると,「スガハラ」でも「スガワラ」でもマッチします.[]の中に何文字が入れると,これらのうちのいずれかが含まれればよいという指定になります
Rubyでは正規表現のパターンであることを指定するために//でくくって指定しますので,正確には下記のとおりになります
/FUJISH?IMA/
/スガ[ハワ]ラ/
指定したファイルから,該当する文字列を含む行を検索するというプログラムを使って練習してみよう
まず下記の架空の名簿をmeibo.txtという名前をつけて保存しよう(emacsに貼り付けた上で保存する).
丘本秋子 | オカモト アキコ | 角館 | OKAMOTO Akiko |
高梁缶 | タカハシ カン | 浦上 | TAKAHASHI Kan |
仁科牧子 | ニシナ マキコ | 所沢 | NISHINA Makiko |
藤嶌楓 | フジシマ カエデ | 葛飾区 | HUJISHIMA Kaede |
伊井利郎 | イイ トシロウ | 横手 | II Toshiro |
木之元週一 | キノモト シュウイチ | 福岡 | KINOMOTO Shuichi |
多村数馬 | タムラ カズマ | ポートアイランド | TAMURA Kazuma |
砂糖真琴 | サトウ マコト | さいたま市 | SATO Makoto |
藤嶋丸子 | フジシマ マルコ | 黒井須 | FUJISIMA Maruko |
嶋田多香子 | シマダ タカコ | 網走 | SHIMADA Takako |
齋藤由 | サイトウ ユウ | 下関 | SAITO Yu |
高橋麹 | タカハシ コウジ | 平和島 | Takahasi Koji |
渡部すず | ワタベ スズ | ロンドン | WATABE Suzu |
渡辺勇次 | ワタナベ ユウジ | アレフガルド | WATANABE Yuji |
藤島真希 | フジシマ マキ | 歩歩露 | FUJISHIMA Maki |
次に,以下のプログラムをkensaku.rbという名前をつけて保存しよう
#!/usr/koeki/bin/ruby while line=gets if /sai?to/i =~ line print line end end
保存をしたら,実行してみます.実行する際には検索したいファイル名を指定する必要があります
irsv{naoya}%chmod +x kensaku.rb irsv{naoya}%./kensaku.rb meibo.txt 砂糖真琴 サトウ マコト さいたま市 SATO Makoto 齋藤由 サイトウ ユウ 下関 SAITO Yu
続いてプログラムの内容について解説します
getsはキーボードから入力された値を文字列として取得するメソッドと説明していました.しかし実際には入力を行うのはキーボードとは限りません.特に指定をしなければキーボードからの入力が求められますが,プログラム実行時にファイルを指定すると,そのファイルの中味を読み込みます
今回の場合,プログラムを実行する際に./kensaku.rb meibo.txtとしていますので,getsメソッドはキーボードからの入力を待たずに,meibo.txtファイルを1行ずつ読み込みます
meibo.txtは15行ありますので,while line=getsは15回繰り返されます.これ以上読むデータがなくなるとwhileの繰り返しは終了します
このifで読み込んだ行が検索パターン(正規表現)にマッチしているか判定を行います.正規表現にマッチしているかどうかは
正規表現 =~ 文字列
と表現します./sai?to/は正規表現の指定で「saito」もしくは「sato」をあらわします./の後ろにあるiは「大文字と小文字を区別しない」という意味を付加するもので,必要に応じてつけたり,つけなかったりします.iをつけない場合は「sato」はマッチしますが「SATO」はマッチしなくなります
なお,正規表現の後ろの=~は「正規表現がマッチする場合は」という比較演算子です.「正規表現がマッチしない場合には」を意味する演算子は!~になります
lineという変数には,ファイルから読み込んだ行が入っています.上記の条件に合致する場合に,その行が出力されます
ifに対応するendです
whileに対応するendです
練習
kensaku.rbプログラムの/sai?to/の部分を様々に変更して結果がどうなるか試してみよう
/sai?to/の中を日本語にするとうまく実行できないことが確認できるだろうか
日本語にマッチさせるためには/の後ろにiの代わりにeまたはsをつける必要があります
i:アルファベットの大文字と小文字を区別しない
e:日本語をEUC文字列だと仮定して照合する
s:日本語をShift-JIS文字列だと仮定して照合する
一通り試してみたら,下記の問題について考えてみよう
正規表現によるパターンが英数字のみで書かれている場合,単純に文字列の中にその文字が含まれているかどうかでマッチする,しないを判断します.以下にサンプルを示します.ここで黄色で網掛けされた文字列は正規表現にマッチした文字列,網掛けされていない文字列はマッチしない文字列を表します(以下同じ)
/ABC/#=> ABC, ABCDEF, 123ABC, A1B2C3, AB, abc
/ABC/というパターンはABCを含む文字列であればどんな文字列であってもマッチします.しかし場合によってはABCから始まるもののみを検索したり,最後がABCとなるものを検索することもありえます.「ABCDEF」はマッチするけれど,「123ABC」はマッチしないようにする,もしくは「123ABC」はマッチするけれど,「ABCDEF」はマッチしないようにするためにはどうしたらよいでしょうか
このためには「^」や「$」というような特殊な文字を使用します.これらの特殊な文字はメタ文字と呼び,「^」は行頭マッチング,「$」は行末マッチングを表します.他にもメタ文字は多数ありますが,これらについては後述します.
/^ABC$/#=> ABC, ABCDEF, 123ABC
/^ABC/#=> ABC, ABCDEF, 123ABC
/ABC$/#=> ABC, ABCDEF, 123ABC
イトウもしくはゴトウのように,「イかゴ」のどちらかを含むというような条件を指定したい場合があります.このようにいくつかの文字のうち,その1つを指定したい場合には,マッチさせたい文字の集合を[]で囲みます
[AB]:AまたはB
[ABC]:AまたはBまたはC
[CBA]:上と同じ(順番は関係なし)
[012ABC]:0,1,2,A,B,Cいずれかの文字
このような書き方だと,「AからZの大文字のアルファベット」というような数が多い条件になると記載が大変です.このような場合には[]の中を○-○というようにハイフンを使って範囲で示すことができます
[A-Z]:アルファベットの大文字全部
[a-z]:アルファベットの小文字全部
[0-9]:数字全部
[A-Za-z]:アルファベットの大文字,小文字全部
[A-Za-z_]:アルファベットの大文字,小文字全部とアンダーバー(_)
[A-Za-z_-]:アルファベットの大文字,小文字全部とアンダーバー(_)とハイフン(-)
ハイフンは範囲を示すために使用します.ハイフン自体を検索対象の文字列としたい場合には,最初か最後に書かなければなりません
なお行頭マッチングで使用した^は[]内で使用するとそこで指定されたもの以外の文字という意味になります
[^ABC]:A,B,C以外の文字
[^a-z]:アルファベットの小文字以外の文字
/[ABC]/#=> B, BCD, 123
/a[ABC]c/#=> aBc, 1aBcDe, abc
/[^ABC]/#=> 1, A
/a[^A-C]c/#=> aBcabc
/[ABC][AB]/#=> AB, CA, AA, CCCCA, xCBx, CC, CxAx, C
/[0-9][A-Z]/#=> 0A, 000AAA
/[^A-Z][A-Z]/#=> 1A2B3C
/[^0-9][^A-Z]/#=> 1A2B3C
.(ピリオド):任意の1文字にマッチする.ピリオド1つなら1文字の文字列,3つなら3文字の文字列をあらわす
/A.C/#=> ABC, 012A3C456, AA, AC, ABBC, abc
/aaa.../#=> 00aaabcde, aaabb
\s:空白文字をあらわす.空白,タブ,改行文字とマッチする
/ABC\sDEF/#=> ABC DEF, ABC\tDEF, ABCDEF
\S:空白以外をあらわす
/ABC\SDEF/#=> ABC3DEF, ABC-DEF, ABCDEF
\d:0から9までの数字とマッチする
/\d\d\d-\d\d\d\d/#=> 012-3456, 01234-012345, ABC-DEFG, 012-21
\w:英数字にマッチする
/\w\w\w/#=> ABC, abc, 012, AB C, AB\nC
\A:文字列の先頭にマッチする
/\AABC/#=> ABC, ABCDEF, 012ABC, 012\nABC
\Z:文字列の末尾にマッチする
/ABC\Z/#=> ABC, 012ABC, ABCDEF, 012\nABC, ABC\nDEF
*:0回以上の繰り返しにマッチする
/A*/#=> A, AAAAA, 1, BBB
/A*C/#=> AAAC, BC, AAAB
/AAA*C/#=> 012\nAAC, AC
/A.*C/#=> AB012C, AB CD, ACDE
+:1回以上の繰り返しにマッチする
/A+/#=> A, AAAAA, 1, BBB
/A+C/#=> AAAC, BC, AAAB
/AAA+C/#=> AAC, AC
/A.+C/#=> AB012C, AB CD, ACDE
?:0回または1回の繰り返しにマッチする
/^A?$/#=> A, AAAAA
/^A?C/#=> AC, AAAC, BC, C
/AAA?C/#=> AAAC, AAC, AC
/A.?C/#=> ACDE, ABCDE, AB012C, AB CD
():*+?と組み合わせて使用することで,1文字単位での繰り返しではなく,複数の文字列の繰り返しにマッチする
/^(ABC)$/#=> ABC, ABCABC, ABCABCAB
/^(ABC)+$/#=> ABC, ABCABC, ABCABCAB
/^(ABC)?$/#=> ABC, ABCABC, ABCABCAB
|:いくつかの候補の中からどれか1つに当てはまるものにマッチする
/^(ABC|DEF)$/#=> ABC, DEF, AB, ABCDEF
/^(AB|CD)+$/#=> ABCD, ABCABC, ABCABCAB
課題
様々な正規表現の表現方法について説明したが,これらを実際に使って試してみよう.具体的には下記の手順に従って実施すること
作成したdata.txtやプログラム,実行結果をメールでnaoya@e.koeki-u.ac.jp宛に送る.
課題の提出期限は6月11日(土)17:00までです
メール送信時の注意
今回はプログラムの作成は求めておらず,様々な正規表現について実施した結果をまとめるというものである.それゆえ,評価を行う上では使用した正規表現の種類や,複雑さを考慮する(最低でも10種類以上は試してみること)
課題を行う上では,/^x...?$/という正規表現を使用したら○○と□□がマッチしました,というように適当に行うのではなく,例えば,フジシマにマッチし,シマダにマッチしないようにするために/^x...?$/という正規表現を用いた./^x...?$/は〜〜という意味であり○○の理由でフジシマにはマッチするが,シマダにはマッチしないためである.実行結果は下記のとおりであり,正しくフジシマのみにマッチした,というように目的意識を持って行うこと
そのためには,正規表現を使って様々なパターンマッチングを行うことができるようなdata.txtを作成する必要がある
したがって,Webページに記載されているまま,例えば/ABC/,/^ABC/を試してみて,1つも該当するものがありませんでしたというのは評価しない.データを見ながらマッチするものがあるような正規表現をいかに数多く考えるか,いかに複雑な方法で指定してマッチするものを見つけることができるかを見る
つまり,今回の課題はいかに巧くdata.txtを作成できるかが重要となる.今回は相談しなければできない課題ではないため,data.txtは各自で作成すること.重複した内容のレポートが提出された場合には,どちらがどちらを写したのか特定できないため,双方とも減点する