こんにちは。リノです。
今回は、PHPで使われている後方参照についてお伝えします。
僕自身後方参照はあまり使うことがないのですが、正規表現に興味があってメモしていたので、皆さんにお伝え出来ればと思います。
後方参照の概要
後方参照の概要についてまずお伝えしていきます。
後方参照を使うことで、あるサブパターンにマッチした文字列が、続く部分に再度現れるかどうかを調べられる。
と説明されていることが多いのですが、理解が難しいかと思いますので、詳しく説明していきます。
まず、サブパターンについて。
サブパターンとは、「(」と「)」で括られた範囲のことを意味します。
aaa(bbb)ccc
という文字があったとき、「(」と「)」で括られている(bbb)がサブパターンを意味します。
で、このサブパターンにマッチした文字列を抜き出すときに使うのが、「/1」や「/2」といった後方参照と呼ばれるものです。
「/1」は1つ目のサブパターンにマッチした箇所、「/2」は2つ目のパターンにマッチした箇所を意味します。(環境によっては、「/1」ではなく、「\1」と記述することもあります。)
後方参照/1のサンプル例
例文を書いてみます。
([a-z])
→これは、aからzまで文字列全てに全部マッチします。(サブパターンの中に入っている文字列のマッチング正規表現)
([a-z])/1
→「/1」の部分が後方参照を表しています。(サブパターンの後ろにひっついているのが後方参照です。
この
([a-z])/1
に対して、1文字目にaを入れると、/1はaにマッチするようになります。というのも、
後方参照を使うことで、あるサブパターンにマッチした文字列が、続く部分に再度現れるかどうかを調べられる。
とあるように、aは正規表現の([a-z])にマッチしているので、/1はこの「a」が再度続くかどうかを調べる機能を有するにようになります。したがって、([a-z])/1の正規表現にマッチするには、
「aa」
という文字列が必要になります。仮に、
([a-c])([d-z])/1
と書かれた正規表現があった時は、「aya」や「cyc」がマッチするようになります。
解説すると、1つ目のサブパターンが([a-c])で、2つ目のサブパターンは([d-z])を指しています。ここで例題の、([a-c])([d-z])/1は「/1」と書かれているので、「/1」は、([a-c])のマッチした部分を指すようになります。
したがって、ayaと入れたとき、([a-c])の正規表現に最初の1文字目のaがマッチし、2文字目のyは([d-z])にマッチします。最後に、ayaの3文字目のaが「/1」にマッチします。
後方参照/2を使ったサンプル例
次に/2を使ってみます。以下のようなコードがあったとき、
([a-c])([d-f])/2
/2は、サブパターンの2つ目である([d-f])にマッチするようになります。よって、
addという文字列は「([a-c])([d-f])/2」という正規表現にマッチします(/2が2文字目のサブパターンdにマッチしているので、ddと続くのは正しい)が、
afaと書けばマッチしません。(/2が2文字目のfとマッチするのに、3文字目にaと書かれているので、マッチしない。3文字目がfならばマッチ。)
後方参照の発展サンプル例
最後にちょっとだけ発展した後方参照のコード例題を書いてみます。
([a-c])([d-f]).\1
この場合は、\1は([a-c])にマッチするようになります。また、コード内のドットは任意の一文字を表すので、「adda」と書いた場合にマッチします。詳しく説明すると、、、
1文字目a→([a-c])にマッチ
2文字目d→[(d-f])にマッチ
3文字目d→ドットにマッチ(任意の1文字にマッチ)
4文字目→\1は最初の([a-c])を指しているから、aにマッチするようになります。
まとめ
今回は後方参照について書いてみました。
僕が初めて後方参照を見た時は、なんだこれ??となってかなり焦っていたので、皆様が躓くような事がなければと思います。