Posix Basic Regular Expression language は、テキストのパターンを 記述するための記法である。正規表現はパターンと文字列とがマッチするかどうかを 検査するためであるとか、文字列に含まれる部分文字列を検索するのに良く使われる。
この章ではPOSIXの正規表現記法について説明する。 ここにあるのはPOSIXの正規表現に関する 正式な定義でもなく、精密な定義でもない。
最も単純なものでは、正規表現はそれ自身にマッチするリテラル文字列である。 たとえば以下のようなパターン
regexp
は、“regexp”という文字列にマッチし、それ以外のものにはマッチしない。
一部のキャラクターは、正規表現中に現れたときに特別な意味を持つ。それら
のキャラクターは先の例のようにリテラルとしてはマッチせず、より一般的な
パターンを意味する。たとえば *
というキャラクターは、直前の要素
の0回以上のくり返しを表すのに用いられる。
smooo*th
上記のパターンにある *
はその直前にある o
が 0回以上くり
返せるということを示している。このため、このパターンは以下のものにマッ
チする:
smooth smoooth smooooth smoooooth ...
*
のような特殊キャラクターにマッチするパターンを書きたいとしよう
-- 言い換えれば、*
が直前のものの繰り返しを表さないようにし、リテ
ラルとして*
にマッチさせたいということだ。これは、特殊キャラクタ
ーをバックスラッシュでクォートすることによって可能となる。
smoo\*th
ようなパターンは
smoo*th
という文字列にマッチし、それ以外のものにはマッチしない。
パターンが予約されている七つの状況がある --
バックスラッシュは特殊キャラクターを通常のものにするのではなく
特殊なものにする。
+
, ?
, |
, (
, )
は通常のキャラクターであるが、
\+
, \?
, \|
, \(
,
\)
, \{
, \}
といったシーケンスは特殊である
(それぞれの意味は後述)。
本章の残りのセクションでは、正規表現で使うことのできる様々な特殊キャラ クターの紹介と解説を行う。
正規表現リテラルとは、一つも特殊キャラクターを含まない文字列である。正 規表現リテラルはまったく同じ文字列にマッチし、その他のキャラクター並び にはマッチしない。例を挙げよう:
literally
は
literally
にマッチし、その他のものにはマッチしない。
一般的には、空白(whitespace)キャラクター、数字、文字は 特殊ではない。一部の句読点キャラクター(punctuation caharacters)は 特殊であるがそうでないものもある (この章の最後にある構文のまとめは、キャラクターが特殊かそうでない かを見分けるのに便利だろう)。
このセクションでは、特殊キャラクター .
と [
を紹介する。
.
はNULLキャラクターを除く任意のキャラクターにマッチする。例を挙
げよう:
p.ck
matches
pick pack puck pbck pcck p.ck ...
[
はキャラクター集合(character set)を開始する。キャラクター
集合はただ一つのキャラクターにマッチするわけではないという点で.
と似ているが、マッチするキャラクターの集合を選べるという点が異なってい
る。[
では.
と違ってキャラクターの集合を陽に定義する。
キャラクター集合で使うことのできる基本的な形式は三種類ある。
第一の形式は、キャラクターの集合をいちいち書くというものである:
[<cset-spec>] -- <cset-spec>にある全てのキャラクターが集合に含まれる。
第二の形式は、陽に列挙したキャラクター集合の補集合を指示するものである:
[^<cset-spec>] -- <cset-spec>に*ない*全てのキャラクターが集合に含まれる。
<cset-spec>
は、いずれにしろキャラクター集合の
陽な列挙である。これは、個々のキャラクターの文字列として
記述することができる:
[aeiou]
あるいは、キャラクターの範囲として記述することもできる:
[0-9]
これら二つの形式を混ぜることも可能である:
[A-za-z0-9_$]
(*
のような)特殊な正規表現キャラクターは、キャラクター集合の中で
は特殊ではないということに注意するように。先の例にあったように、
-
は特殊である。ただし、以下の例にあるようにキャラクター並
びの先頭にある場合は除く。
以下の例はキャラクター四つの集合である:
[-+*/]
キャラクター集合の第三の形式は、あらかじめ定義された “キャラクタークラス”を使用するものである:
[[:class-name:]] -- class-nameで表されるキャラクターが集合に置かれる
サポートされているキャラクタークラスは以下の通り:
alnum - アルファベット、数字の集合 alpha - アルファベットキャラクターの集合 blank - タブとスペース cntrl - 制御キャラクター digit - 十進数字 graph - 空白を除くすべての印字可能キャラクター lower - 小文字 print - “印字可能”(printable)キャラクター punct - 句読点 space - 空白キャラクター upper - 大文字 xdigit - 十六進数字
さらに、キャラクタークラス集合は反転することもできる:
[^[:space:]] - すべての非空白キャラクター
キャラクターセットは、正規表現中のリテラルキャラクターが置けるところな らどこででも使うことができる。
部分式とは、\(
と \)
とに囲まれた正規表現である。部分式は、
単一のキャラクターやキャラクターセットを使えるところであればどこででも
使うことができる。
部分式は、正規表現の構造をグループ化するのに便利である。たとえば、繰り
返し演算子 *
は通常、直前のキャラクターに作用する。
smooo*th
matches
smooth smoooth ...
部分式を使うことで、 *
をより長い文字列に適用できる:
banan\(an\)*a
これは以下のものにマッチする
banana bananana banananana ...
部分式はまた、後方参照と置換に関して特別な意味も持っている (セクション Backreferences, Extractions and Substitutionsを参照)。
*
は繰り返しの演算子である。この演算子は、その直前にある
キャラクター、キャラクターセット、部分式、後方参照(backreference)に
作用し、その要素が0回以上繰り返すことができることを示す。
bana\(na\)*
matches
bana banana bananana banananana ...
\+
は *
と似ているが、\+
は
直前の要素を少なくとも一つ要求する点が異なる。このため:
bana\(na\)*
これは以下のものにマッチするが
bana
bana(na\)\+
こちらはマッチしない。
banana bananana banananana ...
これらは両方ともマッチする。
したがって、bana\(na\)+
は banana\(na\)*
を
短くした記述である。
\?
は、その直前にあるキャラクター、キャラクターセット、
部分式が省略可能(optional)であることを示す。この演算子は
それがマッチしてもよいし、スキップしてもよいことを表す。
CSNY\?
これは、
CSN
と
CSNY
の両方共にマッチする。
非負の整数であり、 n >= m
という関係になっている\{m,n\}
は nterval expression と呼ばれ、その直前にあるキャラクター、キャラクタ
ーセット、部分式、後方参照に対して作用する。この演算子はその直前に置か
れている要素がm
回以上n
回まで繰り返されていなければならな
いことを示す。
例を挙げよう:
c\([ad]\)\{1,4\}
これは
car cdr caar cdar ... caaar cdaar ... cadddr cddddr
にマッチする。
選択(alternative)は以下のように記述される:
regexp-1\|regexp-2\|regexp-3\|...
これは regexp-n
のいずれにもマッチする。例を挙げよう:
Crosby, Stills, \(and Nash\|Nash, and Young\)
これは
Crosby, Stills, and Nash
と
Crosby, Stills, Nash, and Young
にマッチする。
後方参照は \n
のように記述される。ここでn
は0以外の一桁の数字である。
正しい後方参照のためには、最低でもn
個の(かっこで括られた)部分
式がパターン中で後方参照に先行して存在していなければならない。
後方参照は、対応する部分式にマッチしたものの そのままのコピーにマッチする。例を挙げよう:
\(.*\)-\1
matches: これは
go-go ha-ha wakka-wakka ...
といったものにマッチする。
一部のアプリケーションにおいては、部分文字列を取り出すために部分式が使
われている。たとえば、Emacsは match-beginnning
や match-end
といった部分式がマッチした文字列の位置を報告する関数を持っている。これ
らの関数は後方参照と同じ方法で部分式の番号づけを行うが、部分式 0が正規
表現全体となるという規則が増えている。
部分式を文字列の置換のために使用するアプリケーションもある。これもまた、 後方参照と同じの番号づけ規則を使用する。例えば以下のような sedのコマン ドは
s/From:.*<\(.*\)>/To: \1/
まず以下のような行にマッチする:
From: Joe Schmoe <schmoe@uspringfield.edu>
このとき、部分式 1はs "schmoe@uspringfield.edu"にマッチしている。この コマンドは、部分式の置換を行った後でマッチした行を "To: \1"で置き換えて 以下のような結果をもたらす。
To: schmoe@uspringfield.edu
まとめると、正規表現には以下のようなものがある:
abcd
-- リテラル文字列にマッチする
.
-- NULL以外の全てにマッチする
[a-z_?]
, ^[a-z_?]
, [[:alpha:]]
,
[^[:alpha:]]
-- キャラクターセットにマッチする
\(subexp\)
-- 式を部分式にグループ化する
\n
-- n番目の部分式にマッチしたもののコピーにマッチする
以下に挙げた特殊キャラクターおよびシーケンスは、 キャラクター、キャラクター集合、部分式、後方参照に対して 適用可能である:
*
-- 直前の要素の0回以上の繰り返し。
\+
-- 直前の要素の1回以上の繰り返し。
\?
-- 直前の要素の0回もしくは一回の繰り返し。
{m,n}
-- 直前の要素のm
以上n
以下の繰り返し。
regexp-1\|regexp-2\|..
-- regexp-n のいずれかにマッチする。
.
や *
のような特殊キャラクターは
\
を前置することによってリテラルとして扱うようにできる。
\+
や \?
といった特殊シーケンスは
\
を取り去ることによってリテラルとして扱うようにできる。
正規表現は曖昧に見えることがある。たとえば
begin\|beginning
のようなパターンを
beginning
という文字列と比較したと考えてみよう。
これは最初の5文字がマッチするのだろうか、あるいは文字列全体がマッチするの だろうか。
このような場合にはより長い方が優先されるので、文字列全体が マッチする。
どのくらいのキャラクターがマッチするか、ということではなく部分式がどこ
にマッチしたかということについて曖昧さが生じる場合がある。これは、Emacs
の match-beginning
のような抽出関数や、sedのs
コマンドのよ
うなrewrite関数に影響を及ぼすかもしれない。例えば以下のようなパターンの
マッチングを考えてみよう:
b\(\[^q]*\)\(ing\)?
これを以下の文字列に対して適用する
beginning
一つの可能性は、最初の部分式が“eginning”にマッチして 二番目の部分式がスキップされるというものである。 もう一つの可能性は、最初の部分式が“eginn”にマッチして 二番目の部分式が“ing”にマッチするというものである。
可能な限り多くのキャラクターにマッチするという規則があり、 後に登場する部分式の長さが最大化されるのではなく、 より小さな番号の部分式の長さが最大化される
先の例の場合、可能な二つのマッチは全長において等しい。 したがって、より小さな番号の部分式である\1が最大化される。 正解は \1は“eginning”にマッチし、\2はスキップされるという ものである。