"Regular Expression" #3
Riue ちゃんの正規表現講座 / 其参
さて、今回は前回説明した「.」と「*」をサポートする表現を
2 つ取り上げます。適用範囲が時として大きすぎる「.」と
「*」の代わりに使うと、効果テキメンです。
文字集合の表現
其弐で説明した文字の表現方法は、
- 「a」「6」「%」のように、直にタイプした文字。英語で言えば「じゃすとたいぷいん」ってやつですね。
- 「
.」。どのような1文字にでもマッチするメタキャラクタ。
でした。とは言え、もう少し便利な表現方法はないのでしょうか? 例えば、
- 数字だけしかマッチしてほしくない
- アルファベットの小文字だけしかマッチしてほしくない
- 「1」か「2」か「y」以外にマッチしてほしい
- Macintosh がある職場にしてほしい
- 人妻か女子高生じゃないとやだやだ
なんていう希望が出て来ることもあるでしょう(最後の 2 つは余分ですが)。
とにかく、「『.』より意味を限定したい」ということはよくあります。
「.」は便利ですが、どんな 1 文字にでもマッチしてしまいますから、
ちょっと範囲が広すぎるんですよね。
そのような場合は、次のようにしてみましょう。
[(任意の文字が幾つか)]
ちょっと表現が悪いのですが…。
「[」と「]」で囲った間に、任意の文字を入れて使います。
例えば「[abc]」や、「[123]」のような感じです。
これは、
「『[』と『]』に囲まれた文字のうちのどれか 1 文字」
を意味する正規表現になります。
ちょっと例を出してみましょう。
[Tt]his「this」でも「This」でもマッチする正規表現です。
PowerPC 60[134]これは、「『PowerPC 60』という文字列に続いて、『1』か『3』か『4』が続く文字列」という意味になります。 だから「PowerPC 604」や「PowerPC 603」、「PowerPC 601」の3つがマッチする文字列となります。
Bill [Gh]ates同様に、この場合は「Bill Gates」か「Bill hates」にマッチします。 ただ、前者は真っ当な人間とは言えませんし(失礼)、 後者は目的語がないと真っ当な英文とは言えませんね(S + V + O、 でしたっけ? とりあえず、O には Ellison とでも入れておきますか)。
なお、「[]」を使った正規表現は、
一見複数の文字(文字列)を表しているように見えますが、
「[」から「]」までで
1 文字を表現していますので、混乱しないようにして下さい。
でも沢山の文字を指定するのは面倒だぞ
「[]」を使うと、「この文字とこの文字しかマッチしてはいけません」
といったことが簡単に表現できるのですが、実はちょっとした問題が出てきます。
まず、前節で書いた「数字だけを表現する文字」「アルファベットの小文字だけを表現する文字」というのを、
それぞれ「[]」で表現してみましょう。
[0123456789]
[abcdefghijklmnopqrstuvwxyz]
…面倒ですね。「数字 3 桁」なんてものを表現しようものなら、
[0123456789][0123456789][0123456789]というような表現になってしまいます。
実際のところ、「ある文字が指定回数連続する文字列」というのは、 もう少し簡単に表現できます。これについては、後程説明します
「アルファベットの大文字又は小文字が 4 文字並んだ文字列」を表現するためには…いや、やめておきましょう。
そこで、ちょっと便利な表記法が用意されています。
「[0123456789]」という正規表現は、実は次のように表現できます。
[0-9]これは、「『0』の文字コードから、『9』の文字コードまでの文字コードを持つ文字の集合」を表現してます。 「0」の文字コードは 0x30、「9」の文字コードは 0x39 です。
尤も、いきなり「文字コード」と言われても困る方もおられるかもしれませんね。 ここでは文字コードについては詳しくは取り上げませんので、今すぐ詳しく知りたい方は、その手の文献を参照して下さい。 ただ、ASCII をベースにした一般的なコード体系においては、
[0-9A-Za-z]
の順番に並んでいる、と考えればいいでしょう。
このように、「-」を使うと、「[from-to]」
という表現が、簡単に出来るのです。
「[]」と「-」を使った例を、幾つか出してみましょう。
-
[A-Za-z] -
A から Z までの全ての文字と、a から z までの全ての文字…つまりアルファベット全体、です。
-
[.+~_0-9] -
「.」「+」「~」「_」と数字、です。
-
[-4] -
「
[]」を使って「-」という文字を表す場合は、「[]」内の先頭、又は最後に「-」を書くようにします。 これで「-」が「文字コードの範囲を示すメタキャラクタ」として扱われなくなります。 勿論、この「[-4]」が示す正規表現の意味は、「- または 4 のうちのどちらか」ですね。 -
[[567] -
「
[」という文字は、「[]」の中のどこに置いても構いません。 この例では「[ または 5、6、7 のうちのいずれかの文字」と意味します。 -
[]123] -
「
]」を「[]」の中に置く場合は、「[」とは異なり、 必ず「[]」の先頭に置かなくてはなりません。 途中に「]」を置くと、そこで「[]」が終ってしまうからです。 -
[.*] -
「.」と「*」にマッチします。「
[]」内では、 次に述べる「^」以外のメタキャラクタは全て意味を失い、単なる文字として扱われます。
さて、「[]」を使って「文字コードの範囲を指定する」場合には、一つだけ鉄の掟というものがあります。それは、「小さいほうから大きいほうへ書く」ということです。
これはどういうことかと言いますと、
「[0-9]」を「[9-0]」と書いてはいけない、ということです。
勿論、「[a-k]」を「[k-a]」と書いてもいけません。
貴様ら全部否定してやる
「0 から 9 の間にある文字(つまり、数字 10 種類)」という指定が出来るのでしたら、
逆に「数字以外の文字(つまり、0から9以外の文字)」という指定が出来ても良さそうなものですよね。
「[]」には、そのための記法も用意されています。
^
「[]」中の文字列の先頭に「^」を置いた場合、
「『^』に続く文字以外の文字」にマッチする正規表現となります。
「^」の使い方の例を見てみましょう。
-
[^0-9] -
0から9以外の文字…つまり、数字以外の文字にマッチします。
-
[^abc] -
a、b、c以外の文字にマッチします。
-
[ab^] -
a、b、^ にマッチします。このように、「
^」が 「[]」内で先頭以外の位置に置かれた場合、 メタキャラクタとしては扱われず、単に「^」という文字として扱われます。
「連続回数」の指定
其弐では、「任意の文字の 0 文字以上の連続」を表現するために、
「*」を使用する、というようなお話をしました。
でも、「*」だと「直前の文字がどのくらい連続しているのか」ということが表現出来ません。
場合によっては、「5 が 2 個から 5 個並んでいるような文字列」というような指定をしたいこともあるでしょうし、
「3 桁の数字」なんていう指定をしたいこともあるでしょう。
そこで、次のような表現形式が登場します。
\{m\}\{m,\}\{m,n\}
うーん、これだけでは流石に分かりにくいですね。というわけで少し説明しましょう。
この正規表現は、基本的には「*」と全く同じです。
つまり、「直前の文字の連続」を表現するためのものです。
「*」と同じということは、
当然ながら「必ず直前に何らかの文字が必要」というわけですね。
そうでないと、「どの文字の連続か」ということが表現出来ません。
ここで使われている「m」と
「n」は、所謂「任意の数」です。
つまり、m と n には、好きな数を入れて構わないわけです。
ここでは 3 つのパターンを挙げましたが、これはそれぞれ、
- 直前の文字が m 個連続した文字列
- 直前の文字が m 個以上連続した文字列
- 直前の文字が m 個以上 n 個連続した文字列
という意味になっています。ちなみに、m と n はそれぞれ 255 以下の値と決まっています。
そうそう、m と n を囲んでいる「\{」と「\}」。
本来、この正規表現は
{m}{m,}{m,n}
とでも書くべきものなのです。でも、
「{」と「}」にメタキャラクタとしての意味を持たせるために、
敢えて「{」と「}」の直前に「\」を付けて
「\{」と「\}」
と書くようにしているのです。
ま、こんなものは定義を説明するよりも例を見ていただいたほうが速いですね。
-
5\{3\} -
「『5』という文字が 3 個連続した文字列」を表現します。ですから、 「555」がマッチする文字列ですね。
-
[0-9]\{3\} -
上と同様に「数字が 3 桁連続した文字列」を表現します。
-
g\{4,\} -
「『g』という文字が 4 個以上連続した文字列」です。 「gggg」や「gggggggg」がマッチする文字列です。が、当然ながら「g」や「ggg」はマッチしません。
-
M\{2,5\} -
「『M』という文字列が2個以上5個以下連続した文字列」です。 「MM」「MMM」「MMMM」「MMMMM」がマッチの対象になります。それ以外の文字列はマッチしません。
ところで、其弐では「任意の文字列の 1 文字以上の連続」を表現するためには
― 例えば、「h」という文字の1文字以上の連続を表現するには ―
「hh*」を使う、ということをお話ししました。
それでは、「\{m,n\}」を使ってこれを表現出来ないものでしょうか?
もちろん可能です。
が…普通は「h\{1,\}」とタイプするよりも
「hh*」のほうが速いですよね。
「\{\}」の制限
こんなに便利な「\{\}」なのですが…実は、少しばかり制限もあります。
実は「\{\}」は環境によって使えたり使えなかったりするのです。
具体的に言いますと、ed レベル(「其壱」を参照して下さい) の正規表現ではサポートされているのですが、egrep レベルの正規表現ではサポートされません。 というわけで、egrep を使う時は要注意ですね。
とりあえずのおしまい
というわけで、今回は、
「[]」と「\{\}」
について説明させて頂きました。 この 2 つは、使いこなすと非常にに強力なパワーを発揮するので、ぜひ覚えて下さい。
それでは、次回またお会いしましょう。