正規表現
正規表現(regular expression)とは、文字列のマッチパターンを表現する方法です。 正規表現を使うと、テキスト・データ・レコード内の特定のパターンにマッチする文字列を探し出して修正することができ、テキスト・データを操作するユーティリティ・プログラムやプログラミング言語でよく使われます。 正規表現は非常に強力です。
しばしば混同されるのですが、シェルなどのワイルドカードとして知られる glob とは異なります。
文法
編集ここでは特定のプログラミング言語やソフトウェアによらない基本的な正規表現の文法を解説し、個々の文法や具体的なパターンマッチの方法についてはそれぞれの言語やソフトウェアのページに譲ります。
POSIX(Portable Operating System Interface)は、異なるUNIX系システム間で互換性を確保するための標準インターフェースです。POSIX正規表現は、この標準の一部として採用された正規表現の規則です。
基本的なPOSIX正規表現は、基本的なパターンマッチング機能を提供します。文字や文字列のパターンを指定してマッチングを行う際に、特定のメタ文字(.、*、^、$など)を使用します。ただし、特定の拡張機能は提供されません。
一方、POSIX拡張正規表現は、より多くの機能を提供します。例えば、基本正規表現にはない文字クラスや量指定子の拡張が含まれます。この拡張は、より複雑なパターンのマッチングや検索を可能にし、より柔軟な操作ができます。
基本正規表現と拡張正規表現の主な違いは、提供される機能の範囲にあります。基本正規表現は、シンプルなパターンマッチングに使われることが一般的ですが、複雑なマッチングやパターン操作を行う場合は拡張正規表現の利用が推奨されます。
POSIX基本正規表現のメタ文字の一覧
編集メタ文字 | 解説 |
---|---|
. | 任意の1文字にマッチする。たとえば .ook という正規表現は "book" や "cook" などにマッチする。文脈によっては改行文字にマッチする場合もある。
|
* | 直前の正規表現の0回以上の繰り返し。たとえば .* という正規表現は任意の1文字の0文字以上の繰り返しなので、すべての文字列にマッチする。
|
^ | 行頭にマッチする。例えば ^Wikipedia はWikipedia とWikipedia日本語版 にマッチするが、日本語版Wikipedia にはマッチしない。
|
$ | 行末にマッチする。例えば Wikipedia$ はWikipedia と日本語版Wikipedia にマッチするが、Wikipedia日本語版 にはマッチしない。
|
[string] | 文字列stringに含まれる任意の1文字にマッチする。たとえば [bcl]ook は "hook" と "sook" にはマッチしないが、"book" と "cook" と "look" にマッチする。
|
[^string] | 文字列stringに含まれない任意の1文字にマッチする。たとえば [^bcl]ook は "hook" と "sook" にはマッチするが、"book" と "cook" と "look" にマッチしない。
|
[S-E] | 文字Sから文字Eの間の任意の1文字にマッチする。たとえば、[A-C] は "A" "B" "C" にマッチする。
|
[^S-E] | 文字Sから文字Eの間にない任意の1文字にマッチする。たとえば、[^A-C] は "A" "B" "C" 以外にマッチする。
|
- 例
^abc
: "abc"で始まる行にマッチ。abc$
: "abc"で終わる行にマッチ。a[bc]
: "a"の後に"b"か"c"が続く文字にマッチ。a[^bc]
: "a"の後に"b"か"c"以外の文字が続く文字にマッチ。ab*
: "a"の後に"b"が0回以上続く文字列にマッチ。a\{2,4\}
: "a"が2回以上4回以下続く文字列にマッチ。
これらは基本的なPOSIX正規表現の一部です。特定の実装や環境によっては、異なる挙動をすることがありますので、詳細はその環境のドキュメントを参照することをお勧めします。
POSIX拡張正規表現での追加メタ文字の一覧
編集メタ文字 | 解説 |
---|---|
\ | メタ文字の意味を打ち消し、メタ文字自身を表す。 |
? | 直前の正規表現の0回または1回の繰り返し。直前の文字があってもなくてもマッチすることを意味する。たとえば s?he は "she" と "he" にマッチする。
|
+ | 直前の文字の1文字以上の繰り返し。たとえば Goo+gle という正規表現は "Google" や "Gooogle"、"Goooooooogle" などにマッチするが、"Gogle" にはマッチしない。
|
regexp1|regexp2 | regexp1またはregexp2にマッチする。 |
(regexp) | 正規表現をグループ化する。括弧の中の文字列を1つのかたまりとして扱う。たとえば Wiki(books)? は "Wiki" または "Wikibooks" にマッチする。
|
regexp{m,n} | regexpのm回以上n回以下の繰り返し。たとえば、we{2,4}k は "week" "weeek" "weeeek" にマッチする。
|
- 例
(abc|def)
: "abc"または"def"にマッチ。a(bc)+
: "a"の後に"bc"が1回以上続く文字列にマッチ。a?b
: "b"または"ab"にマッチ。(abc)\1
: "abcabc"にマッチ。a\|b
: "a"または"b"にマッチ。a\+
: "a+"にマッチ。
これらのメタ文字は、基本的な正規表現を拡張し、より複雑なパターンのマッチングを可能にします。しかし、環境によってはサポートされない場合があるため、実際の挙動を確認するためにはその環境のドキュメントを参照することが重要です。
サポートしているソフトウェア
編集正規表現は、コマンドラインツール、プレーンテキストエディタ、プログラミング言語など、さまざまなソフトウェアツールでサポートされています。 これらのツールのほとんどは、Unix、Linux、Windows、Mac OS Xなどの様々なコンピューティングプラットフォームで利用できます。 これらのツールは、それぞれ微妙に異なる構文を採用しています。いくつかの注目すべきものを見てみましょう。
正規表現を使用するツールは以下の通りです。
- コマンドラインツール
- grep
- egrep
- sed
- awk
- プレーンテキストエディタ
- ed
- vi(ex)
- emacs
- プログラミング言語
- Java
- JavaScript
- Perl
- PHP
- Python
- Ruby
- Tcl
正規表現は、より大きなテキストセットからサブセットを見つけたり、分離したりする小さなコンピュータプログラムと考えることができます。 通常のコンピュータプログラムがそれを実行するためにコンピュータを必要とするのと同じように、正規表現はそれを解釈し、意味を与えるためのソフトウェア・アプリケーションを必要とします。
PCRE
編集PCRE(Perl Compatible Regular Expressions)は、Perlと互換性のある正規表現ライブラリです。これは、Perlの正規表現エンジンを元にして作られ、C言語で実装されています。PCREは、多くのプログラミング言語やツールで利用できるようになっており、さまざまな環境で正規表現を利用する際の基盤として広く採用されています。
PCREは、POSIX正規表現と比べて機能が豊富で、Perlとの互換性を持っているため、より複雑なパターンマッチングや文字列操作が可能です。文字クラス、量指定子、キャプチャなど、様々な拡張機能が含まれており、高度なパターンマッチングを実現します。
このライブラリは、C言語をベースにしているため、C言語を使用するプログラムだけでなく、Python、PHP、JavaScriptなどの多くのプログラミング言語でもPCREの機能を利用することができます。 PCREは、柔軟性とパワフルな機能を提供することから、広く使われています。
PCRE1とPCRE2
編集PCRE(Perl Compatible Regular Expressions)は、バージョン1(PCRE1)とバージョン2(PCRE2)の2つのメジャーバージョンがあります。 PCRE1は初期のバージョンであり、多くのシステムで広く利用されています。これはPerlとの互換性を重視し、多くの機能を提供していますが、いくつかの制約や改善の余地がありました。 PCRE2は、PCRE1の改良版であり、より多くの新機能や改善が追加されています。PCRE2では、性能の向上、メモリ効率の改善、新しい機能の追加などが行われています。UTF-16/UTF-32サポート、改良されたバックトラックエンジン、より大規模なパターンのサポートなどがその特徴です。 PCRE2は、より最新の機能やパフォーマンスを求める場合に選択されることがありますが、PCRE1はまだ多くのシステムやプロジェクトで使用されています。選択肢は使用環境やニーズによって異なりますが、PCRE2はPCRE1の機能拡張版として、多くの点で改良されています。
PCRE以外の正規表現エンジン
編集PCRE以外にも多くの正規表現エンジンが存在します。それらは、さまざまなプログラミング言語や環境で使用されています。いくつかの代表的な正規表現エンジンを以下に挙げます:
- JavaScriptの正規表現エンジン:JavaScriptには、組み込みのRegExpオブジェクトがあります。このエンジンは、ブラウザやNode.jsなどのJavaScriptランタイムで使用され、パターンマッチングや置換などの機能を提供します。
- Pythonのreモジュール:Pythonのreモジュールは、正規表現をサポートするための組み込みモジュールです。このモジュールは、Pythonの標準ライブラリに含まれており、パターンマッチングや置換、検索などの機能を提供します。
- Javaのjava.util.regexパッケージ:Javaでは、java.util.regexパッケージが正規表現をサポートしています。このパッケージを使用することで、Javaプログラム内でパターンマッチングや置換を行うことができます。
- Rubyの正規表現エンジン:Rubyには、組み込みの正規表現エンジンがあります。これは、Ruby言語で正規表現を利用するための機能を提供します。
- Perlの正規表現エンジン:Perlは、正規表現の機能が最初に広く使われた言語の一つであり、その正規表現エンジンは非常に強力で柔軟です。
これらの正規表現エンジンは、それぞれ言語や環境に組み込まれており、その特性や機能、使いやすさが異なる場合があります。特定のニーズや使用する言語に応じて、適切な正規表現エンジンを選択することが重要です。
C言語で正規表現を使う例
編集C言語で正規表現を使うためには、通常、regex.hヘッダーファイルを使用し、正規表現ライブラリ関連の関数を利用します。
以下は、簡単な正規表現を使った文字列のマッチングの例です。
#include <stdio.h> #include <stdlib.h> #include <regex.h> int main() { regex_t regex; // 正規表現パターン char *pattern = "Hello.*world"; // 正規表現のコンパイル int reti = regcomp(®ex, pattern, 0); if (reti) { fprintf(stderr, "正規表現のコンパイルエラー\n"); exit(EXIT_FAILURE); } // マッチング対象の文字列 char *str = "Hello beautiful world"; // 文字列のマッチング reti = regexec(®ex, str, 0, NULL, 0); if (!reti) { printf("文字列 '%s' はパターンにマッチします\n", str); } else if (reti == REG_NOMATCH) { printf("文字列 '%s' はパターンにマッチしません\n", str); } else { char msgbuf[100]; regerror(reti, ®ex, msgbuf, sizeof(msgbuf)); fprintf(stderr, "正規表現の実行エラー: %s\n", msgbuf); exit(EXIT_FAILURE); } // 正規表現の解放 regfree(®ex); return 0; }
- 実行結果
文字列 'Hello beautiful world' はパターンにマッチします
この例では、regcomp()で正規表現をコンパイルし、regexec()で文字列をマッチングしています。regcomp()やregexec()はエラーチェックが重要です。regfree()を使用して最後にメモリを解放することも重要です。 正規表現のパターンやマッチング対象の文字列を変更することで、別のマッチングを試すことができます。また、正規表現のオプションを変更することで、マッチングの挙動を制御することも可能です。