正規表現とか
パーサーを作る上で避けては通れない正規表現。
「文法理解しとる?理解しとるかお前!」と聞かれたら「NO!!!」と力強く言えるので、勉強します。
でも、欲しいところを掠めとるだけなら(.*?)だけでいい気はするんだよね!
基本的にパターン文字列を作るときは、PHP正規表現チェッカーを使っています、はい。
文法の種類
使える文法の量は、基本 < POSIX < Perlで増えていく。
POSIX
POSIXは、POSIXクラスという文字区分を定義でき、例えば"[:upper:]"みたいに書くと"[A-Za-z]"と同じ意味を持つ。
便利といえば便利だが、POSIXクラスを使わずに普通に"[A-Z]"と書いた方が分かりやすかったりする。
"[:space:]"は"[ \t\n\r\f\v]"と同じ意味を持つので便利なのかも。あまり色々なスペースに対応しなきゃいけない正規表現を書いたことが無いのでわからないんだけども…。
どちらかといえば、拡張することで、"+"(1回以上の連続する文字)、"?"(0または1回だけの文字)、"|"(OR)の3つのメタ文字が使えるようになることのほうが利点が大きい。
文法
Amazon.co.jp: 改訂 新Linux/UNIX入門: 林 晴比古: 本によると、
以下の6種類が基本的な正規表現記号(メタ文字)として取り上げられているので、それをば。
記号 | 説明 |
^ | より外なら行先頭。内なら否定 |
$ | 行の末尾 |
. | 任意の一文字 |
* | 直前の文字の0回以上の繰り返し |
[] | []内の任意の1文字 |
/ | メタ文字のエスケープ |
これ以上のメタ文字を使う場合は、だいたいそれはPOSIXかPerlで拡張する必要があるものだと考えて良い、はず。
実際6つだけで事足りることも多いが、Perlに慣れてしまうと、「くっそ!"?"使えないとか詰んでるし!」となる。
文字クラス
"[ ]"は文字クラスとも呼ばれ、"[abc]"とすると「aかbかcのどれか一文字」にマッチする。"[a-z]"という書き方をすると「a,b,c,...,x,y,zのどれか一文字」にマッチする。
"[ ]"の中でしか使えない文法もあるので以下にまとめておく。
記号 | 説明 |
- | 範囲 |
^ | 先頭に置くと「以外にマッチ」 |
a-z | 小文字の半角英文字 |
A-Z | 大文字の半角英文字 |
0-9 | 数字 |
下3つは定型句みたいな感じの書き方だけども覚えておいて損は無い。
あと、"[A-Za-z]"で半角英数字にマッチになる。
"-"の範囲は文字コードに依存の順番に寄る点に注意。
Unicode対応 文字コード表を見てみるとわかるけれども、UTF-8だとAは41、Zは5A、aは61、zは7Aになっている。
なので、A-zは良くても、a-Zはエラーが返る。
あとZとaの間に"\]^_'"の記号が含まれているので"[A-z]"は『半角英文字』を意味せず、『一部記号と半角英文字』を意味するよくわからん感じになるので、半角英数字をマッチさせたい場合はちゃんと"[a-zA-Z]"としましょう。
実際に使ってみる
対象とするfileには、以下のような文字列が書かれているとする。
% cat file abcde a0b1c2d3 bob tom jon abc123 123abc
それをgrepを用いて行検索をしてみる。
% grep "a" file abcde a0b1c2d3 abc123 123abc % grep "^a" file abcde a0b1c2d3 abc123 % grep "$3" file a0b1c2d3 abc123 % grep "^[a-z]" file abcde a0b1c2d3 bob tom jon abc123 % grep "c[0-9]" file a0b1c2d3 abc123 % grep "a*d" file abcde a0b1c2d3 % grep "a.b" file a0b1c2d3
文字列置換をする場合には、sedやperlを使う。
perlを使うと、Perlの正規表現が使えて便利。
% cat bfile boom bomb bob % sed "s/b.*?b/---/g" < bfile boom bomb bob % perl -pe 's/b.*?b/---/g' < bfile ---om---ob
()で囲むと後方参照ができる(sedは基本となる正規表現の文法しか使えないので\(\)で囲む必要がある)。
()で囲んだ箇所を\1、\2、…とすることで後方参照できる。
% perl -pe 's/(bo)/\1ooo/g' < bfile booooom boooomb boooob
おわりに
正規表現に関してまとめ、使ってみた。
行検索する場合のgrep、文字列置換を行いたい場合のsedやperlで正規表現の出番はあるため、しっかりみにつけておく必要があるな、と感じた。
パターン文字列を作るときは、試行錯誤的になりがちなので、正規表現を簡単にチェックしてくれるようなサービスを使えば、捗ると思うよ!
参考資料
Amazon.co.jp: 改訂 新Linux/UNIX入門: 林 晴比古: 本, p130-p135.
UNIXの部屋 コマンド検索: sed, http://x68000.q-e-d.net/~68user/unix/pickup?sed.
Linuxコマンド集 - 【 grep 】 文字列を検索する:ITpro, http://itpro.nikkeibp.co.jp/article/COLUMN/20060227/230786/.