基礎1 : 正規表現
基本的な正規表現の覚書(その1)です。
本文の表記法
- 「」で囲まれた文字列は正規表現を表す。文脈より明らかな場合は省略あり。
- “をダブルクウォート、’をシングルクウォートと呼び、単にクウォートと呼ぶときは両方を指す。
正規表現の構成
正規表現は特殊文字であるメタ文字(metacharacter)とメタ文字以外のリテラル(literal)と呼ばれる通常のテキスト文字で構成される。
部分パターン
正規表現の一部を部分パターン呼ぶ。
(例) 「te(st|xt)」の場合「(st|xt)」は「te(st|xt)」の部分パターン。
正規表現のメタ文字と親言語やシェルのメタ文字
正規表現のメタ文字と正規表現を利用するプログラム言語(Perl,PHP,Java,C#,VBなど)の文字列におけるメタ文字は別物であり区別をしっかりとする(シェル(DOSプロンプト,Viなど)なども同様)。
表1 メタ文字比較表
| メタ文字 | 正規表現 | DOSプロンプト | PHPの”文字列内 |
|---|---|---|---|
| . | メタ文字:任意の一文字 | メタ文字ではない | メタ文字ではない |
| ? | メタ文字:直前の0or1回繰返し | メタ文字:任意の一文字 | メタ文字ではない |
| * | メタ文字:直前の0回以上繰返し | メタ文字:ワイルドカード | メタ文字ではない |
| ¥t | メタ文字:タブ | メタ文字ではない | メタ文字:タブ |
正規表現「.」は任意の一文字を表すメタ文字。DOSプロンプの.やPHPの文字列としての”.”や’.'はピリオドを表す通常の文字※。
正規表現の「*」は直前の文字の0回以上の繰返しを表すメタ文字。DOSプロンプトではワイルドカードを表すメタ文字。PHPの文字列中の”*”や’*'はアスタリスクを表す通常の文字※。
※1:PHPでは文字列の表記法として”と’で囲む2種類の方法がある。
正規表現のタブを表すメタ文字「\t」とPHPの”文字列内でタブを表すメタ文字”\t”はたまたま同じ表記\t。しかし双方は別物である(\nなども同様)。
DOSプロンプトで正規表現(egrepの例)
c:egrep>egrep "^(?:From|Subject):(.*)" filepath;
DOSプロンプトで”(ダブルクォート)で囲まれた文字列内のメタ文字*はDOSプロンプトのメタ文字*とは解釈されず、通常のリテラル*としてegrepに渡される。egrepは渡された*を正規表現のメタ文字「*」として解釈する。”で囲まない場合、上記の*はDOSプロンプトのメタ文字ワイルドカードとして解釈される。
PHPで正規表現
PHPのmb_ereg_match()は引数として”や’で囲まれた通常の文字列リテラルを受け取る。PHPは”文字列の\tや\nを自身のメタ文字タブ,改行として解釈する。PHPの”文字列内で正規表現のメタ文字として、PHPのメタ文字と重なるメタ文字を渡す場合は\\nのようにをエスケープする必要がある。
- (1)mb_ereg_match(”¥t”) ⇒ まずPHPが¥tを自身のメタ文字タブとして解釈してから正規表現へタブを渡す。
- (2)mb_ereg_match(”¥¥t”) ⇒ PHPは\\tを円記号\と文字tと解釈して正規表現に文字列¥tを正規表現へ渡す。正規表現は¥tをメタ文字「¥t」として解釈。正規表現のメタ文字「¥t」はタブを表すので、結果的には(1),(2)は同じタブを表す。
PHPの’文字列のメタ文字は’のみである。それ以外の文字(¥n,¥tなど)は通常の文字として正規表現に渡される。
mb_ereg_mach(’¥t’) ⇒ 正規表現の「¥t」として解釈される。
表2 PHPのメタ文字
| 記号 | “文字列” | ‘文字列’ |
|---|---|---|
| ¥n | ラインフィールド | メタ文字ではない |
| ¥r | キャリッジリターン | メタ文字ではない |
| ¥t | タブ | メタ文字ではない |
| ¥ | バックスラッシュ | 末尾に限りバックスラッシュ |
| $ | ドル記号 | メタ文字ではない |
| ¥” | ダブルクォーテーション | メタ文字ではない |
| ¥’ | メタ文字ではない | シングルクォーテーション |
正規表現でのエスケープ
正規表現のエスケープは下記の3種類のタイプがある。
- (1) ¥とメタ文字の組み合わせは、リテラルになる。¥*は、リテラル「*」とマッチする。
- (2) ¥と非メタ文字の一部を組み合わせるとメタ文字列となる。「¥t」はタブを表すメタ文字列となる。
- (3) ¥とその他の文字の組み合わせは、¥が無視される。「¥a」は¥が無視され単にリテラル「a」とマッチする。
PHPの”文字列のエスケープ
- (1)¥とメタ文字の組み合わせは、リテラルになる。”¥$”は、文字$を表す。
- (2)¥と非メタ文字の一部を組み合わせるとメタ文字列となる。”¥t”はタブを表すメタ文字列となる。
- (3)¥とその他の文字の組み合わせは、そのまま解釈される”¥w”は円記号と文字wとして解釈される。
マッチ(最長一致,最短一致)
?,*,+,{min,max}などは量指定子と呼ばれる。正規表現の基本は最長一致。しかし、量指定子によってマッチを制御することができる。
?,*,+,{min,max}
量指定子?,*,+,{min,max}は、最長一致。つまり少しでも多くマッチしようとする。
例1 : 「([0-9a-zA-Z]+)([0-9]+)」をabc123にマッチさせる
([0-9a-zA-Z]+) ⇒ abc12
([0-9]+) ⇒ 3
例2 : 「”(.*)”」をMy name is “findx” “fine”にマッチさせる
“(.*)” ⇒ “findx” “fine”
※「*」は最長一致のため「.*」は出来るだけ多くの文字とマッチしようとする。そのため、findx” “fine”までマッチする。しかしそのままでは正規表現「”(.*)”」は最後の”とマッチするものがなく、マッチ不成功になる。よって.*は”一文字を譲りfindx” “fineとマッチする。量指定子?,*,+,{min,max}は最長一致だが、全体のマッチの成功を必ず優先させる。全体マッチためには最小限のものを正規表現エンジンへ譲りわたす(上記の例では”一文字を譲る)。
??,*?,+?
量指定子(?,*,+)に?を付けけた??,*?,+?は最短一致である。つまり少しでも少なくマッチしようとする。
例1 : 「([0-9a-zA-Z]+?)([0-9]+)」をabc123にマッチさせる
([0-9a-zA-Z]+?) ⇒ a
([0-9]+) ⇒ bc12
例2 : 「([0-9a-zA-Z]*?)([0-9]+)」をabc123にマッチさせる
([0-9a-zA-Z]*?) ⇒ なし
([0-9]+) ⇒ abc12
?+,*+,++
?+,*+,++は?,*,+と同様に最長一致である。しかし?+,*+,++は、?,*,+と異なり、一度マッチしたものは全体マッチのためであっても変更しない。
例1 : 「([0-9a-zA-Z]++)([0-9]+)」をabc123にマッチさせる
([0-9a-zA-Z]+?) ⇒ abc123
([0-9]+) ⇒ マッチ不成功
例2 : 「([0-9a-zA-Z]*+)([0-9]+)」をabc123にマッチさせる
([0-9a-zA-Z]*?) ⇒ abc123
([0-9]+) ⇒ マッチ不成功
後方参照
正規表現で一致したパターンの一部を、後で利用するため記憶しておく機能を後方参照
文字列 <a href="http://www.exsample.com/index.html">findxfine</a> 正規表現 <a href="([^"]*)">([^< ]*)</a> 置換文字列 \1 \2; 置換結果 http://www.exsample.com/index.html findxfine
コメントはまだありません。
コメントの投稿
改行と段落タグは自動で挿入されます。メールアドレスは表示されません。
利用可能な HTML タグ :
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite="">
<cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>