Next: , Up: Syntax of Regexps   [Contents][Index]


34.3.1.1 正規表現内の特殊文字

以下は正規表現内で特別な文字のリストです:

.(Period)

これは改行を除く1文字にマッチするスペシャル文字。結合を使用して‘a.b’のような正規表現を作成できる。これは‘a’で始まり‘b’で終わる3文字の文字列にマッチする。

*

これはそれ自身が構成要素ではない。これは前置された正規表現を可能な限り繰り返したものにマッチすることを意味する後置演算子である。したがって‘o*’は任意の個数の‘o’にマッチする(‘o’を含まない場合にもマッチする)。

*’は常に前置された表現の最小の表現に適用される。つまり‘fo*’は‘o’の繰り返しであり‘fo’の繰り返しではない。これは‘f’、‘fo’、‘foo’、...にマッチする。

マッチを行う処理は構成要素‘*’をマッチングにより即座に見つけ得る回数分処理して、その後にパターンの残りを継続する。これが失敗したら残りのパターンのマッチが可能になるかもしれないという期待のもとに、‘*’の変更された構成のうちいくつかのマッチを破棄することでバックトラッキングが発生する。たとえば文字列‘caaar’にたいして‘ca*ar’をマッチングすると、‘a*’はまず3つすべての‘a’へのマッチを試みる。しかし残りのパターンは‘ar’であり、マッチ対象に残されているのは‘r’だけなので試みは失敗する。‘a*’にたいする次の代替策は、2つの‘a’だけへのマッチである。この選択では残りのregexpのマッチは成功する。

警告: ネストされた繰り返し処理は、それらが曖昧なマッチとなるような場合には無期限な長時間の実行となり得る。たとえば文字列‘xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxz’にたいして正規表現‘\(x+y*\)*a’のマッチを試みると、それが最終的に失敗するまでに数時間を要す可能性がある。Emacsはその試みのいずれも機能しないと結論する前に、‘x’のグループ化のそれぞれを試みなければならない。さらに悪いことに‘\(x*\)*’は無数の方法でnull文字列にマッチ可能なので無限ループを引き起こす。これらの問題を避けるにはネストされた繰り返しがバックトラッキングでの組み合わせ爆発(combinatorial explosion)が発生しないことを確実にするために注意深くチェックすること。

+

これは‘*’のような後置演算子だが前置された表現に少なくとも1回マッチしなければならない点が異なる。たとえば‘ca+r’は文字列‘car’や‘caaaar’にマッチするが文字列‘cr’にはマッチせず、その一方で‘ca*r’はこれら3つすべての文字列にマッチする。

?

これは‘*’のような後置演算子だが前置された表現に1回、またはマッチしないかのいずれかでなければならない点が異なる。例えば‘ca?r’は‘car’と‘cr’にマッチするが他にはマッチしない。

*?’, ‘+?’, ‘??

演算子 ‘*’、‘+’、‘?’には非欲張り(non-greedy)な変種が存在する。これらの演算子が可能な最長の部分文字列(含まれる表現全体へのマッチと等しい)とマッチするのにたいして、非欲張りな変種は可能な最短の部分文字列(含まれる表現全体と等しい)にマッチする。

たとえば正規表現‘c[ad]*a’を文字列‘cdaaada’に適用すると文字列全体にマッチするが、正規表現‘c[ad]*?a’を同じ文字列に適用すると‘cda’だけにマッチする(ここでマッチが許された表現全体にたいする‘[ad]*?’の可能な最短マッチは‘d’)。

[ … ]

これは‘[’で始まり‘]’で終端される文字候補(character alternative)。もっとも単純なケースでは、この2つのカッコ(brackets)の間にある文字が、この文字候補がマッチ可能な文字。

したがって‘[ad]’は1つの‘a’と1つの‘d’の両方にマッチし、‘[ad]*’は‘a’と‘d’だけで構成された任意の文字列(空文字列を含む)にマッチする。つまり‘c[ad]*r’は‘cr’、‘car’、‘cdr’、‘caddaar’等にマッチする。

開始文字と終了文字の間に‘-’を記述することにより文字候補内に文字範囲を含めることができる。つまり‘[a-z]’は小文字のASCIIアルファベット文字にマッチする。範囲は‘[a-z$%.]’のように個別の文字と自由に組み合わせることができる。これは任意のASCII小文字アルファベットと‘$’、‘%’、またはピリオドとマッチする。しかし1つの範囲の終端文字が別の範囲の開始文字ではないこと。たとえば‘[a-m-z]’は使用しないこと。

文字候補には名前付き文字クラスも指定できる(Char Classesを参照)。これはPOSIXの機能。たとえば‘[[:ascii:]]’は任意のASCII文字にマッチする。文字クラスの使用は、そのクラス内すべての文字を記述するのと等しい。しかし異なる文字数千を含むクラスもあるので後者は実際は実現不可能。文字クラス範囲の上側や下側の境界に出現するべきではない。

文字候補の内部では、通常のregexpスペシャル文字ではスペシャルではない。完全に異なる文字セット‘]’、‘-’、‘^’がスペシャルになる。文字候補に‘]’を含めるには、それを先頭に配置する。‘^’を含めるには、それを先頭以外の場所に配置する。‘-’を含めるには、それを最後に配置する。したがって‘[]^-]’は、これら3つのスペシャル文字すべてにマッチする。ここでは‘\’はスペシャルではないので、これら3つの文字のエスケープに‘\’は使用できない。

以下の範囲にたいする側面はEmacs固有であり、POSIXはこの振る舞いを許容はするが必須ではなく、Emacs以外のプログラムは異なる振る舞いをするかもしれない。

  1. case-fold-searchが非nilなら‘[a-z]’は大文字にもマッチする。
  2. 範囲はlocaleの照合順の影響を受けない。範囲は常にその範囲の境界間に存在するコードポイントを文字セットで表現されるので、たとえCやPOSIXのlocale外部でも‘[a-z]’がマッチするのはASCII文字のみ。
  3. 範囲の下側境界が上側境界より大きければ範囲は空であり何の文字も表現しない。したがって‘[z-a]’は常にマッチに失敗するし、‘[^z-a]’は改行を含む任意の文字にマッチする。ただし逆転した範囲はtypoでないことを明確にするために、常に文字‘z’から文字‘a’にすること。たとえば‘[+-*/]’は意図した4つの文字ではなく、‘/’だけにマッチするので避けること。

ある種の文字候補は、たとえそれらがEmacs内において明確に定義された意味をもっているとしても最良のスタイルとならない。これらには以下が含まれる:

  1. ほとんどすべての文字を範囲の境界にできるとはいえ、文字コードテーブルを記憶している人はほとんどいないので、ASCII文字や数字の自然な順序を守るほうがよいスタイルである。たとえば‘[.-9]’は‘[./0-9]’、‘[`-~]’は‘[`a-z{|}~]’より明確さに劣る。ここではUnicodeの文字エスケープが助けとなる。たとえばほとんどのプログラマーにとっては‘[ก-ฺ฿-๛]’より‘[\\u0E01-\\u0E3A\\u0E3F-\\u0E5B]’のほうが明確だろう。
  2. 文字候補に重複を含めることができたとしても、それを避けるほうがよいスタイルである。たとえば‘[XYa-yYb-zX]’は‘[XYa-z]’より明確さに劣る。
  3. 範囲を単に1文字、2文字、あるいは3文字で表せたとしても、文字をリストするほうがシンプルである。たとえば‘[a-a0]’は‘[a0]’、‘[i-j]’は‘[ij]’、‘[i-k]’は‘[ijk]’より明確さに劣る。
  4. たとえ文字候補の先頭や範囲の上側境界として‘-’を配置できるとしても、文字候補の最後に‘-’そのものを配置するほうがよいスタイルである。たとえば‘[-a-z]’が有効であっても‘[a-z-]’のほうがよいスタイルであり、‘[*--]’が有効だとしても‘[*+,-]’のほうが明確である。
[^ … ]

[^’は補完文字候補(complemented character alternative)を開始する。これは指定された以外の任意の文字とマッチする。つまり‘[^a-z0-9A-Z]’はASCII文字と数字以外の、すべての文字にマッチする。

^’は文字クラス内では先頭に記述されない限り特別ではない。‘^’に続く文字は、あたかもそれが先頭にあるかのように扱われる(言い換えると‘-’や‘]’はここでは特別ではない)。

マッチしない文字の1つとして改行が記述されていなければ、補完文字候補は改行にマッチできる。これはgrepのようなプログラム内でのregexpの扱いとは対照的である。

文字候補のように名前付き文字クラスを指定できる。たとえば‘[^[:ascii:]]’は任意の非ASCII文字にマッチする。Char Classesを参照のこと。

^

バッファーのマッチングの際には‘^’は空文字列、ただしマッチ対象のテキスト内にある行の先頭(またはバッファーのアクセス可能範囲の先頭)だけにマッチする。それ以外のマッチはすべて失敗する。つまり‘^foo’は行の先頭に出現する‘foo’にマッチする。

バッファーではなく文字列とマッチする際には、‘^’は文字列の先頭か改行文字の後にマッチする。

歴史的な互換性という理由により‘^’は正規表現の先頭、または‘\(’、‘\(?:’、‘\|’の後でのみ使用できる。

$

これは‘^’と似ているが、行の終端(またはバッファーのアクセス可能範囲の終端)だけにマッチする。つまり‘x+$’は行末にある1つ以上の‘x’からなる文字列にマッチする。

バッファーではなく文字列とマッチする際には、‘$’は文字列の終端か改行文字の前にマッチする。

歴史的な互換性という理由により‘$’は正規表現の先頭、または‘\(’、‘\(?:’、‘\|’の前でのみ使用できる。

\

これはスペシャル文字(‘\’を含む)のクォートと、追加のスペシャル文字の導入という2つの機能をもつ。

\’はスペシャル文字をクォートするので‘\$’は‘$’、‘\[’は‘[’だけにマッチする正規表現のようになる。

\’はLisp文字列(String Typeを参照)の入力構文(read syntax)内でも特別な意味をもち、‘\’でクォートしなければならないことに注意。たとえば文字‘\’にマッチする正規表現は‘\\’。文字‘\\’を含むLisp文字列を記述するには、別の‘\\’で‘\\’をクォートすることをLisp構文は要求する。したがって‘\’にマッチする正規表現にたいする入力構文は"\\\\"となる。

注意してください: 歴史的な互換性のために、スペシャル文字はそれらがもつ特別な意味が意味を成さないコンテキスト内にある場合には通常の文字として扱われます。たとえば‘*foo’は‘*’が作用可能な前置された表現がないので、通常の‘*’として扱われます。この挙動に依存するのは悪い習慣です。どこにそれが出現しようとスペシャル文字はすべてクォートしてください。

文字候補内で‘\’は何ら特別ではないので、‘-’や‘]’の特別な意味を取り除くことは決してありません。特別な意味をもたないような場合でも、これらの文字をクォートするべきではありません。バックスラッシュ以外の任意の1文字にマッチする‘[^\]’ (Lisp文字列構文では"[^\\]")内でのように、これらの文字が特別な意味をもつ箇所では、これらの文字にバックスラッシュを前置することには正当性があるので、何もそれほど明解にはしないでしょう。

実際には正規表現内に出現する‘]’は文字候補に近接しており、それ故そのほとんどがスペシャル文字です。しかしリテラルの‘[’と‘]’の複雑なパターンにたいしてマッチを試みることも時にはあるかもしれません。そのような状況では文字候補を囲う角カッコがどれなのかを判断するために、regexpを最初から注意深く解析することが必要なときもあるかもしれません。たとえば‘[^][]]’は補完文字候補‘[^][]’ (角カッコ以外の任意の1文字とマッチする)と、その後のリテラルの‘]’により構成されます。

厳密にはregexp先頭の‘[’は特別で、‘]’は特別ではないというのがルールです。これはクォートされていない最初の‘[’で終わり、その後は文字候補になります。(文字クラス開始を除き)‘[’はもはや特別ではありませんが、‘]’は直後にスペシャル文字‘[’があるか、その‘[’の後に‘^’がある場合を除いて特別です。これは文字クラス終了ではない次のスペシャル文字‘]’まで続きます。これは文字候補を終了させて、通常の正規表現の構文をリストアします。クォートされていない‘[’は再び特別となり、‘]’は特別ではなくなります。