#085 正規表現の落とし穴

1999/10/13

<前目次次>


 馴れてくれば便利に使える正規表現であるが、複雑で曖昧な表現を一行で表わそうというものであるから、そこにはいくつかの落とし穴が存在する。あまり触れられない事項であるのでそれをまとめておく。

・シェルの変数展開(ワイルドカード)とは違う

 UNIX系のOSが持っている機能である、ファイル名の展開機能において用いられるワイルドカードでは、似たような記号を使うが、正規表現とは別ものである。ワイルドカードでは、文字クラスの [ ]や[^ ] は正規表現と同様の使われ方をするものの、「?」は任意の一文字、「*」は任意の長さの文字列を表す。ワイルドカードは、ファイル名の指定を容易にするものであり、その表現力は正規表現よりも低い。

・マルチバイト対応か

 ツール自体が漢字、すなわちマルチバイト文字に対応していないと、「.」が1バイト分しか対応しないなど、意図した結果にならないので注意を要する。日本語のエディタやワープロの場合はまず大丈夫であろうが、UNIX起源のオリジナルのgrep, sed, AWK, Perl などは、マルチバイト対応のものかどうか注意すること。また、マルチバイト対応の場合でも原則として1バイト文字と多バイト文字は別に扱われる。例えば「G」と「G」は別のものとして扱われる。大文字と小文字も原則として区別されるが、i オプション(ignoreの意味)をつけると同一視するコマンドもある。

・最左・最長一致の原則

 量指定子(「*」「+」など)を使った正規表現などの場合、マッチする部分が複数ある場合がある。この場合、正規表現は「最も左から、最も長く一致するものにマッチする」という原則がある。例えば「うわー*」という正規表現が「うわーーーー、うわーー、うわーーーーーー」のどこにマッチするのかと言うと、最初の「うわーーーー」になるのである。「うわ」でも「うわー」でもなく、最も左にあり、かつ一番長く一致するようにマッチするのである。特に「.*」などを含む正規表現を不用意に使うと、自分が意図した部分以上にマッチしている場合があり、注意を要する。
 また、マッチするのは原則として最初に見つかったもののみである。繰り返してマッチさせたい場合には、g オプション(globalの意味)をつけるとすべてにマッチするコマンドもある。

・ツールによっては使えないものがある

 先の説明では、Perlを元に説明をしたが、Perlは数ある正規表現の便利なものを全て取り込んだものと言ってよく、grepやsedやAWKでは、これらの一部が使えない場合がある。使えなくても別の方法で表現可能だったりするのだが、サポートしていない正規表現は普通通常の文字と同様に扱われるので、何が使えるのかを把握しておかないと、意図した結果にならないので注意が必要である。
 主なツールやコマンドにおける正規表現は以下の通り。×のついているものは、サポートされていない正規表現である。

使用ツール grep sed awk perl 秀丸 WZ MIFES MS-Word
任意文字 . . . . . . . ?
量指定子(0-) * * * * * * * ×
量指定子(1-) × × + + + + + @
量指定子(0,1) ? × ? ? ? ? ? ×
汎用量指定子 \{m,n\} \{m,n\} × {m,n} × × × {m,n}
文字クラス [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
否定文字クラス [^ ] [^ ] [^ ] [^ ] [^ ] [^ ] [^ ] [! ]
行頭/行末 ^/$ ^/$ ^/$ ^/$ ^/$ ^/$ ^/$ ×
後方参照タグ × \( \) × ( ) × \( \) { } ( )
語頭/語末 × \</\> \</\> \b × × #// </>

・ツールによっては表現が違うものがある

 例えば( )や{ }などは、Perl以外のツールでは「\」をつけるようになっている。Perlでは「\ をつけて別な意味を持つのは英数字のみ」というように統一しており、この方が合理的とも言える。
 また、上で見るとおり、ツールによっては全く違う記号を当てているものもある。特にMS-Wordなどは、その他の正規表現との互換性が低い。UNIXのことなど何も勉強しないで勝手に作っていると言うことがよくわかる。

 というわけで、4回に渡って正規表現について解説してきたが、概念的な話に終始してしまい分かりにくかったかもしれないと反省している。実際のところ正規表現は、いくら聞いてわかったつもりになっても結局は実際に使ってみて初めて馴染んでくるものである。むしろ様々な正規表現を学習した後に、その内容を整理するために見返していただければと思う。


<前目次次>