前節では、正規表現の第1歩として1文字にマッチさせるためのパターンの作り方を見てきました。 この節では、複数の文字にマッチさせるための方法をいくつか紹介します。
といっても、何も大変なことはありません。 複数の文字にマッチさせるには、それらの文字列を正規表現の中で並べればいいのです。 例えば/can/は、cの次にaが来て、その次にnが来る文字列にマッチします。
You can do it!
candy
candle
また/<br>/はHTMLの改行タグにマッチします。 前節で紹介した文字クラスを組み合わせて/<h\d>/とすれば見出しタグにマッチし、/<h\w>/とすれば<hr>にもマッチします。 では、
I can't help eating candy!
という文に対しては、どちらのcanにマッチするのでしょうか? Perlの正規表現ではなるべく左からマッチさせていくので、この場合は"I can't"のcanにマッチします。
次に、"can"か"Can"か"CAN"のどれかにマッチさせたい場合を考えましょう。 正規表現の中の複数の文字列のうちのどれかにマッチさせるには|(縦棒)を使います。 これを使って"can"、"Can"、"CAN"のどれかにマッチさせるには、
/can|Can|CAN/
とします。
"soon"や"moon"など、"oo"と繰り返すような文字列にマッチさせるには「量指定子」を使います。 量指定子にはいろいろな物があるので一つ一つ見ていきましょう。
*(アスタリスク)
*(アスタリスク)は、直前の文字及び文字クラスが0個以上続くような文字列にマッチします。 例えば、
@words = qw(soon moon noon orange water);
foreach (@words) {
if(/o*/){
print "$_ ";
}
}
とすると、"soon"や"moon"等にマッチします。 しかし、上のスクリプトを実行すると"water"にもマッチしてしまいます。 *は、直前の文字及び文字クラスが0個以上続くような物にマッチするので、文字が全くない場合、つまり空文字列にもマッチしてしまいます。 マッチングのときには、文字列の前後や文字の間に空文字列があると解釈されるので"water"にもマッチしてしまうのです。
+(プラス)
+(プラス)は直前の文字及び文字クラスが1個以上続くようなものにマッチします。 上のスクリプトを書き換えて、
@words = qw(soon moon noon orange water);
foreach (@words) {
if(/o+/){ #*を+に変更
print "$_ ";
}
}
としてみましょう。 今度はちゃんと"water"にはマッチしませんね。
?(疑問符)
?(疑問符)は、直前の文字及び文字クラスが0個または1個続くような文字列にマッチします。 ですから、
@words = qw(soon moon noon orange water);
foreach (@words) {
if(/o?/){
print "$_ ";
}
}
を実行すると、@wordsの中の全ての文字列にマッチします。
もっと細かく
*、+、?と3種類の量指定子を紹介してきましたが、これらでは「ちょうど2回」とか「3回以上10回以下」といったような細かい指定は出来ません。 そのような芸当をしてくれるのは{m}、{m,}、{m,n}等の指定子です。 {m}はちょうどm回繰り返し出現するパターンにマッチします。 例えば「けろけろ」にマッチさせるには/(けろ){2}/のように、「けろ」を( )で囲みます。 もし( )で囲むのを忘れてしまって/けろ{2}/とすると「けろろ」にマッチします。
{m,n}指定子は、直前の文字及び文字クラスがm回以上n回以下繰り返し出現するパターンにマッチします。 例えば/(けろ){3,5}/は「けろけろけろ」、「けろけろけろけろ」、「けろけろけろけろけろ」にマッチします。 またm回以上繰り返し出現するパターンにマッチさせるには/(けろ){m,}/のように、2番目の数字を省略します。 さらに、n回以下繰り返し出現するパターンにマッチさせるには/(けろ){0,n}/とします。 /(けろ){,n}/ではないので注意してください。
次の表は、*、+、?をそれぞれ{m,n}指定子を使って表した物です。
指定子 | {m,n}で書くと… |
---|---|
* | {0,} |
+ | {1,} |
? | {0,1} |
最長マッチと最短マッチ
さて、
I can't help loving can.
#え? あ、そう? てれるな〜。
という文の中で"I can"という文字列にマッチさせようとして、
/.*can/
とすると、実際には文末の"can"にマッチしてしまいます。 これは量指定子が、対象の文字列が複数ある場合、最も長い物にマッチしようとする「最長マッチ」の機能を持っているからです。 最も短い範囲でマッチさせるには、使われている量指定子の直後に?をつけます。 上の例の場合、ちゃんと"I can"にマッチさせるには、*のあとに?をつけて、
/.*?can/
とします。
量指定子を使わない正規表現では最短マッチを行います。 この辺は混同しないように注意が必要です。
例えば、
<h1>正規表現</h1>
というような、対になったHTML文にマッチさせるにはどうすればいいでしょうか? 今まで見てきたことを使って、
<.+>.+</.+>
とすればうまく行くでしょうか? でもこれだと、
<h1>正規表現</h2>
にもマッチしてしまいます。 このように、1度マッチしたパターンを憶えておいて、あとでもう1度マッチさせたいというようなときに使えるのが「後方参照」という機能です。 これを使って上の正規表現を書きかえると、
<(.+)>.+</\1>
のようになります。 まず、記憶させたいパターンを( )で囲みます。 そして、もう1度マッチさせたい場所で、\整数という形で呼び出します。 この整数の値は1から始まり、( )で囲まれた正規表現が現れた順番を表しています。 ですから、最初に( )で囲んだ部分は\1によって参照され、次に( )で囲んだ物は\2で参照されるのです。 例えば、
<h1><i>正規表現</i></h1>
にマッチさせるには、
<(.+)><(.+)>正規表現</\2></\1>
とします。
「行頭の"can"」や「行末の"can"」など、文字列が置かれている位置まで指定してマッチさせたい場合には、次のような演算子を使います。
^(キャレット)または\A
^(キャレット)または\Aを使うと、行頭の文字列にマッチします。 例えば、/^can/は、"candy"や"candle"にはマッチしますが、"American"にはマッチしません。
$または\Z
$または\Zは行末の文字列にマッチします。 例えば/can$/は、先ほどの例とは反対に"American"にはマッチしますが、"candy"や"candle"にはマッチしません。
\b
\bは単語の境界(\wと\Wの間)にマッチします。 例えば、/can\b/は、"American"にはマッチしますが、"candy"や"candle"にはマッチしません。
\B
\Bは\bとは反対に単語の境界以外にマッチします。 ですから、/can\B/は"candy"や"candle"にはマッチしますが、"American"にはマッチしません。
さて、この章の最初に、「僕は」で始まり「猫が好き。」で終わる文にマッチさせるための正規表現を紹介しました。 それは、
/^僕は.*猫が好き。$/
というものでした。 ここまで勉強してこられた皆さんには、これがなぜなのかもうおわかりだと思います。 上の正規表現は、「行頭に『僕は』があり、その後に改行文字以外の文字が0個以上続き、行末に『猫が好き。』が来るような文字列」にマッチします。
いかがでしたか? この章の最初にも書きましたが、正規表現はPerlの強力な武器です。 皆さんもいろいろなパターンをつくって実験してみてください。 次の節では正規表現の拡張機能について紹介します。