ワテの場合、正規表現は初心者に毛が生えた程度だ。
簡単な正規表現パターンを使って検索や置換は出来る。
先読み、後読み、否定先読み、否定後読みなどは時々使うが、その度に文法を思い出すのに苦労する。
それらに関しては、この記事がお勧めだ。
さて、そんな正規表現初心者のワテが最近まで知らなかった正規表現パターンがある。
それがこれだ。
\1
バックスラッシュ1
英語フォントなら円記号はバックスラッシュになる。
後方参照と言うやつだ。英語で言うと back reference。
この記事では、正規表現の後方参照をマスターしよう。
では本題に入ろう。
正規表現の後方参照とは何か?
例えばC#の正規表現でこの後方参照パターンを利用する例を一つあげてみよう。
var regex = new Regex(@"(.)\1+");
でもこれだけでは良く分からないだろう。
なので、このパターンを使ってみる。
以下に示すC#のコンソールプログラムを実行する。
var regex = new Regex(@"(.)\1+"); var regex2 = new Regex("(.)\\1+"); // これでも良い var str = "ゲゲゲの鬼太郎"; Console.WriteLine(regex.Replace(str, "$1"));
なおC#の文字列は @”文字列” のように先頭にアットマークを付けると文字列中にあるエスケープの為の円記号¥は一個で済む。
もし従来通りのアットマークの無い “文字列” の形式なら¥¥のように円記号を二個使う必要がある。
さて、上のコードの実行結果は以下の通り。
実行結果
ゲの鬼太郎
となる。
以下でワテ流に解説しよう。
連続する文字を一個に置き換える正規表現パターン
この正規表現パターンの解説をしよう。
var regex = new Regex(@"(.)\1+");
(.) 任意の一文字
\1 後方参照
+ 直前の文字の1回以上の繰り返し
こんな意味になる。まあこれは正規表現パターンの基本だから誰でも分るだろう。
もし後方参照が無ければ、単純に
(.)+
となるが、これだと任意の1文字の1回以上の繰り返しになる。
従って、入力文字列
"ゲゲゲの鬼太郎"
に対して、
"ゲゲゲ" "の" "鬼" "太" "郎"
の部分文字列がマッチする。
後方参照が入ると以下のようになるが、マッチする部分文字列は上に示したものと同じだ。
(.)\1+
で、この後方参照の使い道であるが、再びソースコードを示すが、
var regex = new Regex(@"(.)\1+"); var str = "ゲゲゲの鬼太郎"; Console.WriteLine(regex.Replace(str, "$1"));
のReplaceの部分で$1で参照しているが、この$1に後方参照した文字列が来るのだ。
今の場合は、\1の直前にあるパターン (.) にマッチした1文字だ。
なのでこの置換によって
"ゲゲゲ" → "ゲ" "の" → "の" "鬼" → "鬼" "太" → "太" "郎" → "郎"
と置換されるので、最終結果は、
ゲの鬼太郎
となる
つまり文字列中にある連続する文字を一個に置き換える正規表現パターンだ。
var str = “ゲゲゲのドドドの鬼太郎”; の場合
上で示した正規表現の後方参照パターンを、別の文字列に適用してみよう。
{ var regex = new Regex(@"(.)\1+"); var str = "ゲゲゲのドドドの鬼太郎"; Console.WriteLine(regex.Replace(str, "$1")); }
その実行結果は以下の通り。
ゲのドの鬼太郎
このように、連続して繰り返し出現する文字列(ゲゲゲ、ドドド)は一個の文字(ゲ、ド)に置換出来る。
ちなみに、ゲゲゲの鬼太郎は知っているが、ドドドの鬼太郎は聞いた事は無い。
後方参照を使わないとどうなるか?
もし上の例で、後方参照を使わないで以下のようにするとどうなるか?
{ // var regex = new Regex(@"(.)\1+"); //後方参照版 var regex = new Regex(@"(.)+"); var str = "ゲゲゲの鬼太郎"; Console.WriteLine(regex.Replace(str, "$1")); }
その実行結果は以下の通り。
郎
その理由をワテ流に解釈するなら、以下の通り。
つまり “(.)+” の正規表現パターンで、キャプチャーグループ (.) は任意の一文字を表す。
なので、まず先頭の「ゲ」がこのキャプチャーグループに入る。
このキャプチャーグループに量指定子 + が付いているから二番目の「ゲ」がキャプチャーグループ (.) に入る(上書きされる)。
以下、その繰り返しで、末尾の「郎」まで来ると、その「郎」がキャプチャーグループ (.) に入る(上書きされる)。
そうすると、量指定子 + はそれ以上マッチ出来ないのでその時点でマッチは終わり。
その結果、キャプチャーグループ $1 には「郎」が入っている。
と言う説明で良いのかな?
ちょっと自信が無いが。
同じ単語の繰り返しを一単語に置き換える正規表現パターン
まあ、あまり使う場面は無いと思うが、応用編として、こんなパターンを書いてみた。
var regex = new Regex(@"(ぴょこ)\1+"); var regex2 = new Regex("(ぴょこ)\\1+"); // これでも良い var str = "かえるぴょこぴょこみぴょこぴょこ 合わせてぴょこぴょこむぴょこぴょこ"; Console.WriteLine(regex.Replace(str, "$1"));
その実行結果は以下の通り。
かえるぴょこみぴょこ 合わせてぴょこむぴょこ
正規表現パターンの説明
(ぴょこ)の後ろに \1 の後方参照を入れているので(ぴょこ)が後方参照の対象となる。
そして + 記号があるので、(ぴょこ)の繰り返し文字列にマッチする正規表現パターンだ。
Replaceでは $1 で後方参照した要素を取り出す。今の場合は(ぴょこ)だ。
なので
ぴょこぴょこ ぴょこぴょこぴょこ
などが
ぴょこ
に変わる。
なお、\1 は後方参照と呼ばれるが、\1 の前の文字とか単語などを取り出す為に使う訳なので、前方参照と呼んだ方が馴染みやすいのでは無いかと思った。
恐らく、後で再利用するから後方参照と言うのだと思う。
後方で参照して利用すると言う感じかな。
あくまでワテの解釈なので、真偽の程は未確認だ。
後方参照は複数個使っても良い
\1だけでなく\2や\3など、幾らでも利用可能だ。
例えば\1と\2を使ってみる。
var regex = new Regex(@"(ゲ)\1+(ビ)\2+"); var str = "ゲゲゲビビビの鬼太郎"; Console.WriteLine(regex.Replace(str, "$1$2"));
その実行結果は以下の通り。
ゲビの鬼太郎
まあ要するに、
ゲゲゲ → ゲ ビビビ → ビ
に置き換わった訳だ。
まああまり使う場面は無いかも知れない。
まとめ
当記事では、正規表現の後方参照の使い方を紹介した。
文字列中に出現する同じ文字の繰り返しを検出して、その文字を一個だけにするなどに利用出来る。
でもまあ、その文字がどんな文字なのか事前に分かっている場合には、わざわざ後方参照を使わなくても良いが。
例えば、矢鱈とセミコロン;が多いこんな文字列が有ったとして、
東京都;;;港区;;;;赤坂;;;;;三丁目
セミコロンを全部取り除くのではなくて、一個だけは単語の区切り記号として残しておきたい。
東京都;港区;赤坂;三丁目
こんなふうにしたい。
そう言う場合には、後方参照でもいいが、後方参照を使わない普通のパターンでも可能だ。
{ // 後方参照版 var regex = new Regex(@"(;)\1+"); var str = "東京都;;;港区;;;;赤坂;;;;;三丁目"; Console.WriteLine(regex.Replace(str, "$1")); // ここで後方参照を使う } { // 一般的なパターン var regex = new Regex(@";+"); var str = "東京都;;;港区;;;;赤坂;;;;;三丁目"; Console.WriteLine(regex.Replace(str, ";")); // 置換後の文字は";" に決めているので }
本で勉強する
まあ、楽しく勉強したい人はこんな本もお勧めだ。
超入門とは一体全体どんな入門なのか気になる。
ワテの場合、イデオムと言う単語の意味が分からん。でもアマゾンでは人気があるみたいだ。
この独習C#は有名だ。
アマゾンレビューの評価も高いのでお勧めだ。ただしワテは読んだことは無い。
やっぱり、こう言うポケットリファレンスを鞄に一冊だけしのばせておいて、時々気になった事が有れば辞書代わりに使う、そう言う使い方をしているとあなたも上級者っぽく見えるだろう。
- 単行本(ソフトカバー): 512ページ
- 発売日: 2017/6/20
- 梱包サイズ: 18.8 x 13 x 2.2 cm
なのでコンパクトだが512ページもあるのか!
かなり安値で本を買う(本以外も買えます)
2017年のゴールデンウイークを利用して便利なWEBサイトを作ってみた。
名付けて、
何が出来るかと言うと、
Amazon.co.jp
楽天市場
ヤフーショッピング
の三つのショッピングサイトを同時検索して、商品を価格の安い順に表示出来るお買い物支援サイトだ。
「最安価格サーチ」で、
「Androidプログラミング」をかなり安値で探したい人は こちらから >
「Xamarinプログラミング」をかなり安値で探したい人は こちらから >
「C#プログラミング」をかなり安値で探したい人は こちらから >
「Visual Studioプログラミング」をかなり安値で探したい人は こちらから >
もしお使い頂きまして何かご不明な点、改善案などありましたらお知らせ下さい。
コメント