Next: , Previous: Regexp Search, Up: Search


10.5 正規表現の構文

正規表現には、特別な使い方をする少数の文字と その他の普通の文字から成る構文があります。 普通の文字は、 同じ文字だけに一致してそれ以外には一致しない単純な正規表現です。 特別な文字は、‘$’、‘^’、‘.’、‘*’、‘+’、 ‘?’、‘[’、‘]’、および、‘\’です。 ‘\’が先行する場合を除いて、 正規表現に現れるこれら以外の文字は普通の文字です。

たとえば、‘f’は特別な文字ではなく、通常の文字ですから、 文字列‘f’に一致してそれ以外の文字列には一致しない正規表現です。 (これは、文字列‘ff’には一致しない。) 同様に、‘o’は、‘o’だけに一致する正規表現です。 (大文字小文字を区別しない場合、 これらの正規表現は‘F’や‘O’にも一致するが、 これらは例外というよりは、『同じ文字列』の一般化として捉える。)

任意の2つの正規表現abを連結できます。 その結果は、aが文字列の始めの適当な部分に一致して、かつ、 bが文字列の残りの部分に一致する場合に、 文字列に一致するような正規表現です。

簡単な例として、正規表現‘f’と‘o’を連結すると、 正規表現‘fo’を得ますが、 これは文字列‘fo’だけに一致します。 簡単ですね。 多少とも複雑なことを行うには、特別な文字を使う必要があります。 以下にその一覧をあげます。

. (ピリオド)
特別な文字であり、改行以外の任意の1文字に一致する。 連結を使って‘a.b’のような正規表現を作れる。 これは、‘a’で始まり‘b’で終る任意の3文字の文字列に一致する。
*
単独では構成要素ではない。 直前の正規表現を可能な限り反復することを意味する後置演算子である。 すなわち、(‘o’が存在しない場合も含めて) ‘o*’は任意個の‘o’に一致する。

*’はつねに先行する最小の正規表現に適用される。 したがって、‘fo*’は‘fo’を繰り返すのではなく、 ‘o’を繰り返す。 この正規表現は‘f’、‘fo’、‘foo’などに一致する。

*’を用いた構成は、一致を処理するときには、 ただちに得られる限りの反復回数に展開される。 そうしてから、残りのパターンを処理する。 一致に失敗すると、バックトラック(後戻り)が発生して、 ‘*’を用いた構成の反復回数を減らして、 パターンの残りの部分が一致するようにする。 たとえば、文字列‘caaar’に対して ‘ca*ar’を一致させることを考えてみる。 始めに、‘a*’を3つの‘a’すべてに一致させようとする。 しかし、残りのパターンが‘ar’なのに‘r’しか残っていないため、 この試みは失敗する。 そこで、つぎは‘a*’を‘a’2つだけに一致させる。 こうすると、残りの正規表現も正しく一致する。

+
*’に似た後置演算子だが、 直前の正規表現に1回以上一致する必要がある。 たとえば、‘ca+r’は、文字列‘car’や‘caaaar’には一致するが、 文字列‘cr’には一致ない。 ‘ca*r’の場合は、上記の3つすべてに一致する。
?
*’に似た後置演算子だが、 直前の正規表現に1回だけ一致するか、あるいは、1回も一致しない。 たとえば、‘ca?r’は、‘car’や‘cr’に一致するが、 他のものには一致しない。
[ ... ]
[’で始まり‘]’で終る文字集合を表す。 もっとも単純な場合は、 この2つの中括弧のあいだにある文字の1つ1つがこの文字集合に一致する。

したがって、‘[ad]’は、‘a’1文字か‘d’1文字のどちらにも一致する。 ‘[ad]*’は、‘a’と‘d’だけから成る (空の文字列を含む)任意の文字列に一致する。 このことから、‘c[ad]*r’は、 ‘cr’、‘car’、‘cdr’、‘caddaar’などに一致することがわかる。

文字集合には、文字範囲の指定を含めることもでき、 始めの文字と終りの文字のあいだに‘-’を書く。 つまり、‘[a-z]’はすべてのASCII小文字に一致する。 範囲指定と個々の文字を自由に織り混ぜてよく、 ‘[a-z$%.]’のように書ける。 これは、任意のASCII小文字、‘$’、‘%’、ピリオドに一致する。

文字集合の内側では、正規表現の通常の特別な文字を 特別扱いしないことに注意。 文字集合の内側では、まったく別の特別な文字、 ‘]’、‘-’、および、‘^’が存在する。

文字集合に‘]’を含めるには、 ‘]’を最初の文字として指定する必要がある。 たとえば、‘[]a]’は、‘]’や‘a’に一致する。 ‘-’を含めるのであれば、‘-’を文字集合の最初の文字か 最後の文字として指定して、範囲指定のあとに置く。 したがって、‘[]-]’は、‘]’と‘-’の両方に一致する。

文字集合に‘^’を含めるには、‘^’を文字集合の2番目以降に置く。

大文字小文字を区別する探索で文字範囲を指定するときは、 範囲の両端を、大文字だけ、小文字だけ、あるいは、 英字以外だけで書くべきである。 ‘A-z’のような大文字小文字を混ぜた文字範囲の動作は、 定義が明確ではなく、将来のEmacsでは変更するかもしれない。

[^ ... ]
[^’は文字の補集合の始まりを意味し、 指定した文字を除く任意の文字に一致する。 すなわち、‘[^a-z0-9A-Z]’は、 英文字と数字を除くすべての文字に一致する。

^’は先頭になければ文字集合では特別な意味を持たない。 ‘^’に続く文字は先頭にあるものとして扱われる (いいかえれば、ここでは‘-’や‘]’は特別な意味を持たない)。

文字の補集合は、一致しない文字として改行を指定しない限り、改行にも一致する。 この点は、grepのようなプログラムでの正規表現の扱い方と対照的。

^
空の文字列に一致する特別な文字で、テキスト行の先頭のみに一致する。 それ以外では、一致に失敗する。 したがって、‘^foo’は、行頭にある‘foo’に一致する。
$
^’と似ていて、行末のみに一致する。 したがって、‘x+$’は、 行末にある1文字以上の‘x’から成る文字列に一致する。
\
2つの機能がある。 (‘\’を含む)特別な文字をクォートする(意味を抑える)ことと、 特別な構成を導入すること。

\’は特別な文字をクォートするので、 ‘\$’は文字‘$’だけに一致する正規表現、 ‘\[’は文字‘[’だけに一致する正規表現、 というようになる。

注意: 従来との互換性のために、特別な文字が、 それらの特別な意味をなしえない文脈で使われた場合には、 普通の文字として扱われます。 たとえば、‘*foo’では、‘*’の対象となる正規表現が直前にないため、 ‘*’は普通の文字として扱われます。 このようなふるまいに依存することはよい習慣ではありません。 特別な文字を書く位置に関係なく特別な文字はクォートするべきです。

多くの場合、任意の文字を伴う‘\’はその文字だけに一致します。 しかし、いくつか例外があって、 ‘\’で始まる2文字列が特別な意味を持つ場合があります。 2文字目にくる文字は、 単独で使った場合には普通の文字として扱われるものです。 以下に‘\’の構成を列挙します。

\|
選択肢を指定する。 ‘\|’をあいだに伴った2つの正規表現abは、 abのいずれかに一致する文字列に一致する正規表現となる。

したがって、‘foo\|bar’は、‘foo’か‘bar’に一致するが、 それ以外の文字列には一致しない。

\|’は、周囲にある適用しうる正規表現の中でも最大のものに適用される。 ‘\|’によるグループ化を制限するのは、 これを囲む‘\( ... \)’によるグループ化だけ。

何度‘\|’を使っても処理できるだけの十分なバックトラック能力がある。

\( ... \)
以下の3つの目的を果たすグループ化のための構成。
  1. 他の操作に使うために一連の選択肢‘\|’を括る。 したがって、‘\(foo\|bar\)x’は、 ‘foox’か‘barx’のいずれかに一致する。
  2. 後置演算子、‘*’、‘+’、‘?’を適用できるように、 複雑な正規表現を括る。 したがって、‘ba\(na\)*’は、 ‘bananana’のように、(0個以上の)任意個の 文字列‘na’に一致する。
  3. あとで参照できるように、一致した部分文字列を記録する。

最後の使い方は、括弧によるグループ化という考え方から 派生したものではない。 同一の‘\( ... \)’構成に与えた2つめの別の機能である。 実用上、これら2つの意味が混同されることはない。

\d
d番目に現れた‘\( ... \)’に一致したテキストと 同じテキストに一致する。

一致を処理するときには、‘\( ... \)’構成の末尾に達すると、 この構成に一致したテキストの始めと終りを記録する。 そして、正規表現のそれよりうしろでは、 『d番目に現れた‘\( ... \)’に一致したテキスト』という意味で ‘\’に続けて数字dを使える。

1つの正規表現内に現れる最初の9個の‘\( ... \)’に一致する文字列には、 正規表現中で開き括弧が現れた順に、1から9までの番号を割りふる。 そのため、‘\1’から‘\9’で、 対応する‘\( ... \)’に一致したテキストを参照できる。

たとえば、‘\(.*\)\1’は、改行を含まない文字列で、かつ、 前半と後半が同一である文字列に一致する。 ‘\(.*\)’は前半部分に一致し、それはどのようなものでもかまわない。 一方、それに続く‘\1’は、 前半部分とまったく同じテキストに一致しなければならない。

ある‘\( ... \)’が、 (直後に‘*’がある場合などに簡単に起こりえる) 複数回一致する場合には、最後に一致したものだけを記録する。

\`
空の文字列に一致するが、 一致対象であるバッファや文字列の先頭に限る。
\'
空の文字列に一致するが、 一致対象であるバッファや文字列の末尾に限る。
\=
空の文字列に一致するが、ポイント位置に限る。
\b
同じく空の文字列に一致するが、単語の先頭や末尾に限る。 したがって、‘\bfoo\b’は、単語として独立して現れる‘foo’に一致する。 ‘\bballs?\b’は、単語として独立して現れる ‘ball’や‘balls’に一致する。

\b’は、 バッファの先頭や末尾にあるテキストとは無関係に、 バッファの先頭や末尾にも一致する。

\B
空の文字列に一致するが、単語の先頭や末尾以外に限る。
\<
空の文字列に一致するが、単語の先頭に限る。 ‘\<’は、単語構成文字が続く場合に限って、 バッファの先頭にも一致する。
\>
空の文字列に一致するが、単語の末尾に限る。 ‘\>’は、単語構成文字で終了している場合に限って、 バッファの末尾にも一致する。
\w
任意の単語構成文字に一致する。 エディタの構文テーブルによってこの文字が決まる。 see Syntax
\W
単語構成文字以外の文字に一致する。
\sc
構文がcである文字だけに一致する。 ここで、cは構文コードを表す文字。 たとえば、‘w’は単語構成要素を、 ‘-’は白文字を、‘(’は開き括弧を表すといった具合。 (改行を含む)白文字は、‘-’や空白で表す。
\Sc
構文がcでない任意の文字に一致する。

単語や構文に関連する構成要素は、 構文テーブル(see Syntax)の設定で制御されます。

複雑な正規表現を以下に示します。 これは、任意個の白文字がうしろに続く文末を認識するためにEmacsが使うものです。 空白とタブ文字を区別できるように、Lispの構文で示してあります。 Lisp構文では、文字列定数はダブルクォートで始まり、 ダブルクォートで終ります。 ‘\"’は正規表現の一部としてのダブルクォートを表し、 ‘\\’は正規表現の一部としてのバックスラッシュを表します。 ‘\t’はタブ文字、‘\n’は改行文字を表します。

     "[.?!][]\"')]*\\($\\|\t\\|  \\)[ \t\n]*"

この正規表現は4つの部分が繋がってできています。 ピリオド、‘?’、‘!’のいずれかに一致する文字集合。 閉じ中括、2種類の引用符、括弧に一致する文字集合の任意回数の繰り返し。 バックスラッシュ付きの括弧で括った、 行末、タブ、空白2つのいずれかに一致する選択肢。 白文字に一致する文字集合の任意回数の繰り返し。

これと同じ正規表現を対話的に入力するときには、 タブを入力するには<TAB>を打ち、 改行を入力するにはC-jを打ちます。 また、Lisp構文上ではバックスラッシュを2つ続けてますが、 対話的に入力するには、1つのバックスラッシュだけを打ちます。