日常作業に役に立つ正規表現の使い方(基本編)
僕は日々の作業においてよく正規表現を使います。ソースコードやドキュメント、データの作成・加工・要約やデータなど、多くのテキスト形式のものを扱うために正規表現を使っています。
テキストに関する作業は、正規表現によりとても効率よくなります。というのも、正規表現は単語や文字列パターンの探すのに適しているからです。
今回は、正規表現の基本的な三つの使い方にについて書きます。
基本的な使い方(1) 文字列を見つける
テキストの中から文字列(=文字の並び)を見つけることは、正規表現の最も基本的な機能です。文字列とは言葉通りただの文字列のことで、例えば、
- function
- <td>
- "Hello, World"
- 正規表現
などです。英数字や記号、日本語の文字などを並べただけのものです。
単純な文字列を見つけるための正規表現はとても簡単です。大抵の場合、見つけたい文字列そのものが正規表現です*1。
使用例
- JavascriptやPHPの関数を見つけるために、正規表現「function」を使う。
- HTMLからテーブルのセルを見つけるために、正規表現「<td>」を使う。
基本的な使い方(2) いくつかの候補のうちのどれかに当てはまる(文字列|文字)を見つける
OR検索です。
「(public|protected|private)」という正規表現を使うと、以下の三つの文字列からどれか一つを見つけることができます*2。
- public
- protected
- private
使い方(1)と(2)を組み合わせた正規表現「(public|protected|private) function」では、以下のどれかを見つけられます。
- public function
- protected function
- private function
また、候補に当てはまる文字を見つけるために「[abc]」のような書き方ができます。以下の三つの文字のうちどれか一つを見つけるために使えます。
- a
- b
- c
さらに簡略化した書き方として、「[a-zA-Z]」でアルファベットを、「[0-9]」で数字を見つけることができます。
「[a-zA-Z]」という正規表現は、以下のうちどれかを見つけ、
- a〜z
- A〜Z
「[0-9]」という正規表現は、以下のううちどれかを見つけることができます。
- 0〜9
候補を見つける特殊な書き方として、「[^abc]」のような書き方もあります。これは、aとbとc「以外」の文字どれか一つに当てはまるものを見つけます。したがって、例えば以下のような文字を見つけることができます。
- d
- a
- 1
- 字
「[^a-zA-Z]」のように書けば、アルファベット「以外」の文字を見つけることができます。この書き方はとてもよく使います。
基本的な使い方(3) (文字列|文字)の繰り返しを見つける
連続して現れる文字や文字列を見つける方法がいくつかあります。
どの環境でも大概使えるのが「*」を使った「0回以上の繰り返し」です。繰り返すのは「*」の直前の(文字|文字列)です。正規表現「a*」では、文字aを繰り返した以下のような文字列を見つけられます。
- a
- aa
- aaaaaaaaaaaaaa
- 『長さ0の文字列』
『長さ0の文字列』がいらない場合は、正規表現「aa*」を使うことで、文字aを1回以上の繰り返した文字列を見つけることができます。
文字列の繰り返しを見つける場合、「*」の直前に()で囲んだ文字列を書きます。正規表現「(abc)*」では、以下のような文字列を見つけられます。
- abc
- abcabcabc
- abcabcabcabcabc
- 『長さ0の文字列』
環境によっては「1回以上の繰り返し」を「+」で表すことができます。*3。正規表現「a+」では以下をのような文字列を見つけられます。
- a
- aa
- aaaaaaaaaaaaaa
「a+」は、結局「aa*」と同じことです。したがって、「+」が使えない環境でも問題はありません。
またも環境依存ですが、繰り返しと類似したものとして、「?」を使った「0回または1回」があります。「?」の直前の(文字|文字列)がある場合とない場合の両方を見つけられます。これは、たいていの場合、他の文字列と組み合わせて使います。正規表現「<div( class="section")?>」では、以下のどちらかを見つけることができます。
- <div>
- <div class="section">
「<div( class="section")?>」は、「(<div>|<div class="section">)と同じことです。
使用例
- Javascriptの変数名(長さは問わない)を見つけるために、正規表現「[_a-zA-Z][_a-zA-Z0-9]*」を使う。
- 1文字以上のスペースを見つけるために、正規表現「 +」(※注:+の前に空白が1つある)もしくは「 *」(※注:*の前に空白が2つある)を使う。
- class属性を持つことがあるdivタグを見つけるために、正規表現「<div( class="[a-z]*")?>」を使う。ただし、クラス属性は0文字以上の小文字アルファベットのものだけに限定する。
- Javaの文字列を見つけるために、「"[^"]*"」を使う。
まとめ
正規表現で本当に大事なのは、今回書いた三つの考え方だけです。
- 文字の並び
- 候補の内のどれかひとつ
- 繰り返し
正規表現はすべてこの三つの組み合わせで作ります。
候補や繰り返しの書き方は今回挙げたもの含めて多数あります。環境によっても異なる書き方があります。しかし、これら書き方は表現上の問題であり、枝葉です。今回の三つの基本的な考え方さえわかっていればあとは何とかなります。
三つの組み合わせ意識しながら日常的に使っていれば、正規表現はすぐに使いこなせるようになると思います。
困ったときのためのリンク
それぞれの環境での正規表現の書き方が書かれているページへのリンクです。細かなことで困っときの参照用です。
*1:ただし、特別な意味を持つ文字は、正規表現の中でそのまま使うことができません。そのような文字を含む文字列を検索するためには、エスケープを行い文字の持つ特別な意味を打ち消す必要があります。どの文字が特別な意味を持つかは、環境によって異なります。たとえば、秀丸で「a = 4 * 2;」という文字列を検索するためには、「a = 4 \* 2;」という正規表現を使います。「*」の持つ特別な意味を「\」で打ち消しています。
*2:ただし、viやvimでは「\(public|protected|private\)」と書く必要があります。基本的な機能を使うのためにエスケープが必要な当たりvi/vimは変態的な気もします。テキスト中に頻繁に現れる「(」や「)」の検索が優先されているかもしれませんが、vi/vimでだけこれを区別して使うのは正直面倒です。
*3:例えば、viでは「+」この意味をもちません。