正規表現 実習

Photo by Jasper Garratt on Unsplash

以前学んだように正規表現は大変便利なものであるが、先にある程度慣れておかないといざというときに使えない技術でもある. そこで今回は、ある程度の復習も兼ねて正規表現に慣れ、これからに生かせるようにしよう.

Emacs をインストールしておこう (未インストールの場合)

今回の演習では Emacs を用いるので,自分の Unix環境に Emacs がインストールされていないのであればインストールしておこう.これまで紹介してきた環境だと以下のような感じだ.

環境 状況
阪大情報教育システム
CentOS7
Emacs 24.3.1 がインストール済み(アプリケーション > プログラミング にある)
もちろんこれを用いても良い.
阪大情報教育システム
Windows 10
Windows用 Emacs 25.2.1 がインストール済み(start > documentation にある)
今回はこれを用いても良い.
阪大情報教育システム
cygwin
Emacsは未インストール.
上にあるように Windows 用がインストール済みなのでそちらを使おう.
各自PC CentOS7
obtained at OSBoxes
Emacsは未インストール.
インストール方法をweb検索し,インストールしよう.難しくない.
今インストールするならば,最新の ver. 26.3 が良いだろう.
インストール後は,端末ソフトの中で “emacs” と打ち込めば起動する
各自PC cygwin Emacs が未インストールならばインストールしよう.
cygwin の「パッケージ追加」という文言でweb検索すれば良いだろう
各自PC Windows 64bit版 GNU Emacs 26.3 for Windows(w/IMEパッチ) からダウンロードしてインストールするのが良いだろう
各自PC Mac OS X 通常は未インストールの様子.インストールしよう.
“Mac OS X emacs” などと web 検索して調べて自分でインストールしよう.

簡単な復習

まずは以前の資料 正規表現:「こんな感じのパターンで…」を文字で示す方法 に正規表現の ルール を載せているので、そこを参照しておこう. また、そこに書いてある 「例(2) emacs で…」 を実際に試してないのであれば、今試しておこう.

Emacs での正規表現を便利に (visual-regexp)

Emacs では、正規表現の利用に他環境よりもバックスラッシュ \ を多用する傾向がありちょっとわかりにくい. しかし、visual-regexp.el という elisp を Emacs に導入すると(拡張機能のようなもの)、「正規表現の該当する部分を目で確かめながら」正規表現を入力していくことができるので、これをインストールして, 正規表現をわかりやすく使ってみよう.

package を使ってインストール (おすすめ)

ver.24以降の Emacs では package システム(すぐ下で後述)が標準なので、package の設定が済ませてからインストールすれば良い. 阪大の教育用計算機環境だと Windows の emacs が ver.25 以上なので package が使える.

package そのものの設定

package は ver.24 以降の Emacs に標準でついてくる elisp で、あちこちのリポジトリに登録されている様々な elisp を統一して扱える便利な仕組みである. 阪大教育用計算機システムでこれを使えるようにするには、emacs の設定ファイル(通常は ~/.emacs.d/init.el)のなるべく先頭側に、

1
2
3
4
5
(setq url-proxy-services '(("http" . "toyonakans.ecs.cmc.osaka-u.ac.jp:3128")))

(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/"))
(package-initialize)

という 4行を書き込んでおけば良い(その後、emacs の再起動が必要).
tips: 阪大情報教育システムは外部接続のために最初の行の設定が必要だ.

通常の環境だと,最初の1行は不要で,残りの3行だけ書き込んでおけばよいだろう.

package を使って、実際にインストール

では,Emacs のパッケージ管理システムを実際に使って,visual-regex パッケージを Emacs にインストールしよう. 次のようにすれば良い.

  1. Emacs で M-x package-refresh-contents とする(念のため).
  2. Emacs で M-x package-install とすると、インストールするパッケージ名を聞かれるので、visual-regexp と入力する.
  3. emacs の設定ファイル(通常は ~/.emacs.d/init.el) のなるべく後ろ側に

    1
    2
    3
    
    (require 'visual-regexp)
    (define-key global-map (kbd "C-c r") 'vr/replace)
    (define-key global-map (kbd "C-c q") 'vr/query-replace)

    と書き込む(その後、emacs の再起動が必要).

    手動でインストール (おすすめしないが、古い環境では仕方ない)

    全て手動でインストールしたいという場合は次のように作業することになる. たとえば emacs が ver.23 だというような場合はこの「手動インストール」を選択することになるだろう.

    1.visual-regexp 開発元 から visual-regexp.el をダウンロードし、emacs の load-path (emacs が読み込む elisp ファイルを置く場所)の通ったフォルダに置く. これまでに load-path を設定した覚えのない人は、例えば新しく ~/.emacs.d/elisp というフォルダを自分用に使うと決めて、以下のようにして作っておいて、そこへ入れよう.

    1
    2
    
    cd ~/.emacs.d
    mkdir elisp

    そして、この新しいフォルダ名を、emacs の設定ファイル(通常は ~/.emacs.d/init.el)の先頭の方に

    1
    
    (add-to-list 'load-path "~/.emacs.d/elisp/")

    と書き込むことで emacs の load-path に追加しておこう.
    こうしておくことで、emacs は次の起動時からこのフォルダを認識できるので、emacs をいったん終了して、ふたたび emacs を起動しよう.

    注: emacs の load-path がどう設定されているかを調べたければ、emacs にて M-x describe-variable とすると変数の内容を尋ねることができるので、そこで load-path を尋ねれば良い.

    2.古い emacs に欠けているライブラリ cl-lib の最新版をダウンロードし、cl-lib.el と名前を変えた上で、やはり同様に load-path の通ったディレクトリに置こう. 上で ~/.emacs.d/elisp を作って使い始めた人は、やはりこのフォルダに cl-lib.el を置けば良い.

    3.開発元Installation にあるように emacs の設定ファイル(通常は ~/.emacs.d/init.el)に、

    1
    2
    3
    4
    5
    6
    
    ;; to fix the bug of the visual-regexp for Emacs23.
    (defun custom-initialize-delay (symbol value) ())
    
    (require 'visual-regexp)
    (define-key global-map (kbd "C-c r") 'vr/replace)
    (define-key global-map (kbd "C-c q") 'vr/query-replace)

と書き込む. ただし、最初の行のバグ対応は教官による quick hack である.

Emacs で正規表現の反応を見ながら試してみよう.

次のようにして、visual-regexp を試してみよう.

まず下記の文字列データを Emacs で読み込んでみよう.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 Gender,GivenName,Surname,StreetAddress,City,State,ZipCode,EmailAddress,TelephoneNumber,Birthday,Occupation,Kilograms
 female,Nina,Narita,"1870 Pine Tree Lane",Odenton,MD,21113,NinaNarita@fleckens.hu,240-373-9832,9/17/1942,Erector,50.1
 male,Michinori,Sugiyama,"1651 Beechwood Avenue",Plainfield,NJ,07060,MichinoriSugiyama@gustr.com,908-791-7658,9/26/1932,"Railroad conductor",102.1
 male,Tatsuki,Nozaki,"1224 Pick Street",Walden,CO,80480,TatsukiNozaki@fleckens.hu,970-723-5529,12/23/1962,"Rental clerk",113.2
 male,Kunihiro,Tagami,"2156 Terry Lane",Orlando,FL,32801,KunihiroTagami@rhyta.com,321-273-4846,1/3/1943,"Show host",77.6
 female,Hozumi,Iwasaki,"1380 Nuzum Court",Hamburg,NY,14075,HozumiIwasaki@cuvox.de,716-646-1784,1/28/1989,"Affirmative action coordinator",92.9
 male,Yoshimitsu,Akita,"2602 Masonic Hill Road","Little Rock",AR,72212,YoshimitsuAkita@einrot.com,501-516-6338,8/23/1986,"Multiple machine tool setter",94.9
 female,Chise,Sakuma,"2415 Wildwood Street",Boardman,OH,44512,ChiseSakuma@fleckens.hu,330-716-0474,6/10/1939,"School social worker",73.2
 female,Shirabe,Terada,"1372 Pearl Street","West Sacramento",CA,95691,ShirabeTerada@superrito.com,916-376-5441,8/6/1942,"Public address system announcer",57.8
 female,Yuiri,Fukuhara,"4220 Reeves Street",Milwaukee,WI,53202,YuiriFukuhara@einrot.com,920-827-6614,6/16/1947,"Nutrition director",59.6

なお、これは FakeName データ(zip) に含まれているデータの先頭11行である. このデータは、Fake Name Generator によって作られた Fake Name Generator identities と呼ばれる「偽物の個人データ」であり、Creative Commons Attribution-Share Alike 3.0 United States License によってライセンスされているものである.

まずは見てみるだけ

  1. 次に、Emacs でこの文字列より前にカーソルを置いてから, C-c r とし、^ を入力してみよう. 行頭が指定されたのが分かるだろう. わかったら、C-g で visual-regexp を停止しよう.
  2. 次に、Emacs で C-c r としてから、$ を入力してみよう. 行末が指定されたのが分かるだろう. (以下同様)
  3. 次に、Emacs で C-c r としてから、e\{2\} を入力してみよう. e が2回繰り返された部分が指定されたのが分かるだろう. (以下同様)
  4. 次に、Emacs で C-c r としてから、a\|d を入力してみよう. ad という文字が指定されたのが分かるだろう. (以下同様)
  5. 次に、Emacs で C-c r としてから、\b, を入力してみよう(\b は単語のはじめか終わりを意味する.). 「単語に引き続くカンマ」 が指定され, 他のカンマは指定されていないのが分かるだろうか. (以下同様)
  6. 次に、Emacs で C-c r としてから、\bco\b を入力してみよう. 独立した co だけが指定され, courtcom に含まれる他の co は指定されていないのが分かるだろうか. (以下同様)
  7. 次に、Emacs で C-c r としてから、^[^/]*/ を入力してみよう. 「最初に出てくる / まで」が指定されたのが分かるだろうか. (以下同様)
  8. 次に、Emacs で C-c r としてから、[0-9]+/[0-9]+/[0-9]+ を入力してみよう. 「数字一個以上/数字一個以上/数字一個以上」が指定され, 生年月日部分だけが指定されたのが分かるだろうか. (以下同様)
  9. 次に、Emacs で C-c r としてから、\(female.*\)\([0-9]+/[0-9]+/[0-9]+\) を入力してみよう. Emacs の正規表現のグルーピング \( \) の意味が色でわかるだろう. (以下同様)


置き換えてみよう

  1. 次に、Emacs で C-c r としてから、^ を入力してみよう. 行頭が指定されるので、さらに Enter を押してから、begin とでも入力してみよう. そして、さらに Enter を押して、変化させてみよう. 納得しただろうか.納得したら、M-x undo として、変更を元に戻そう.
  2. 次に、Emacs で C-c r としてから、$ を入力してみよう. 行末が指定されるので、さらに Enter を押してから、C-q C-j と入力してみよう. 交互に空行が入るのが分かるだろう. (以下同様)



    ちなみに,C-j は改行コード LF のことで、C-q はこうした制御コードを(機能させずに)「そのまま」入力するために使うキーである( 機能 quoted-insert のキーバインディング).

  3. 次に、Emacs で C-c r としてから、e\{2\} を入力してみよう. e が2回繰り返された部分が指定されるので、さらに Enter を押してから、EE と入力してみよう. (以下同様)

  4. 次に、Emacs で C-c r としてから、a\|d を入力してみよう. ad という文字が指定されるのでさらに Enter を押してから、ZZZ と入力してみよう.



    さらにこのタイミングで C-c p を何回か押してみよう. どこにどういう変化が起こるのかが予測できるだろう. (以下同様)

  5. 次に、Emacs で C-c r としてから、\b, を入力してみよう. 「単語に引き続くカンマ」 が指定されるので, さらに Enter を押してから、___ などと入力してみよう. (以下同様)

  6. 次に、Emacs で C-c r としてから、\bco\b を入力してみよう. 独立した co だけが指定されるので, さらに Enter を押してから、Colorado などと入力してみよう. (以下同様)

  7. 次に、Emacs で C-c r としてから、^[^/]*/ を入力してみよう. 「最初に出てくる / まで」が指定されるので, さらに Enter を押してから、before birthday/ などと入力してみよう. (以下同様)

  8. 次に、Emacs で C-c r としてから、[0-9]+/[0-9]+/[0-9]+ を入力してみよう. 「数字一個以上/数字一個以上/数字一個以上」が指定され, 生年月日部分だけが指定されるのでさらに Enter を押してから、--removed-- などと入力してみよう. (以下同様)

  9. 次に、Emacs で C-c r としてから、\(female.*\)\([0-9]+/[0-9]+/[0-9]+\) を入力してみよう. Emacs の正規表現のグルーピング \( \) の意味が色でわかるので、さらに Enter を押してから、\1--removed-- と入力してみよう. これは female の生年月日データのみを書き換えたことに相当することが分かるだろう. (以下同様)


自分で考えてみよう

以下の問題を Emacs で行うことを考えてみよう. ただし、できれば、データは今の10人分ではなく, うえでも解説した FakeName データ(zip) に含まれているデータ 1000人分でやってみよう.

  1. このデータは目で見るにはちょっと読みにくいので、全てのカンマの後にスペースを一つ入れたい. どうしたらよいかやってみよう. うまくいったら元に戻そう.
  2. このデータは目で見るにはちょっと読みにくいので、全ての項目を一項目一行にしたい. ただし、一個人のデータのまとまりごとに空行を挟んで区別ができるようにもしたい. つまり、

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
female
Nina
Narita
"1870 Pine Tree Lane"
Odenton
MD
21113
NinaNarita@fleckens.hu
240-373-9832
9/17/1942
Erector
50.1
  
male
Michinori
Sugiyama
"1651 Beechwood Avenue"
Plainfield
NJ
07060
MichinoriSugiyama@gustr.com
908-791-7658
(以下…略…)

のようにしたい.
どうすればいいだろうか. 一回の処理で完成しなくても、複数の処理を組み合わせても良いので、考えてみよう. なお、うまくいったら元に戻そう.

3. このデータの生年月日は 月/日/年 という並びで日本の年月日フォーマットとなじまないので、これを年-月-日という表記, 例えば 1942-9-17 と直したい. どうすればいいか. (以下同様)

4. このデータの行末にはスペースは入っていないはずだが、念の為にそれを確認したい. そして、もしそうしたスペースが有れば、それを削除したい. どうすればいいか. (以下同様)

5. このデータの中に同姓の人が居るかなるべく簡単に調べたい(居るかどうかだけわかれば良い). どうすればいいか. (以下同様)

レポート

以下の課題について能う限り賢明な調査と考察を行い,
2020-AppliedMath7-Report-07
という題名をつけて e-mail にて教官宛にレポートとして提出せよ. なお,レポートを e-mail の代わりに TeX で作成した書面にて提出してもよい.

課題

  1. Fake Name Generator の “一括注文する” (上のタブにある)などで適当な設定で少し多めのデータ(まあ数百人程度にしておくとよいだろう)を作成して、emacs で正規表現を使いながら、10代の人、20代の人、30代の人… と年齢でグループ分けしてみよう.
  2. ここまでの話は英語圏、日本語圏関係なく使えるツールや概念であったが、日本語処理の場合、「漢字」と「よみ」との多対多関係という、他の言語にはあまりない問題が在る. この問題に対しサポートを与える、migemo(今は cmigemo が主か) というツールがあるのでこれについて調べよ. そして、自前の環境にインストールするなどして、その使用感をレビュー、レポートせよ.