正規表現の強力さには日々助けられています。
今回.+
とキャプチャ()
を組み合わせて繰り返しを含むパターンを作る方法を紹介します。
※.*
でも同様に利用できます。
※ 正規表現を気軽に試すには以下のサイトがおすすめです。
キャプチャとは?
分かる方は読み飛ばしてください。
.+
や.*
は正規表現の基礎なので、知っている前提とします。
正規表現のキャプチャとは、パターンの中から文字列を「ひとまとめ」にし、切り出す機能です。
例えば、HTMLタグのなかで、TEXT部分のみ取得したい場合を考えて見ましょう。
例えば、以下のHTMLがあるとします。
私はよく<a href="https://awesome.example.com">素敵なサイト</a>にアクセスします。
ここで、タグの中のTEXT部(つまり今回の例では<a>
の中の素敵なサイト
)を取得するには、以下のようにします。
※簡単のため、パターンは「>
と<
に囲まれた文字列」と表現します。
>(.*)<
()
をつけると、その部分を切り出(キャプチャ) してくれます。
例えば、pythonを使えば次のようにプログラム中で取得できます。
import re test_str = "私はよく<a href=\"https://awesome.example.com\">素敵なサイト</a>にアクセスします。" regex = r">(.*)<" m = re.search(regex, test_str) print(m.group(1)) // 素敵なサイト
このように、正規表現のキャプチャ機能とは、ざっくり言うと()
で指定した部分を「ひとまとめ」にし、切り出す機能です。
「.+」とキャプチャ「()」を組み合わせる
では、早速「.+」とキャプチャ()
を組み合わせて使ってみましょう。
実例を使って考えて見ます。
HTML(XML)のタグにマッチさせる
では、<h1>TEXT</h1>
といった、HTML(XML)のタグにマッチするかどうかを判定するシンプルな正規表現を考えて見ます。
.+
とキャプチャ()
を組み合わせると次のように書けます。
<(.+)>(.*)<\/\1>
※正規表現の機能を説明するためのシンプルな実装にとどめています。厳密にHTMLにマッチする正規表現はもっと考慮すべき点が多くあるため、これより複雑になります。
ポイントは、\1
の部分です。それ以前でキャプチャ()
した内容を参照しています。
便利で感動しますよね!!
これにより、繰り返しを含むパターンを定義できました!!
置換で使う
正規表現を使った置換はプログラムを書くときに強力。
では、 サクッと.*
とキャプチャ()
を組み合わせてsetter
からgetter
を生成してみましょう!
以下は擬似コードですが、setter
を担う関数のシグネチャです。
void set_account_id(string account_id)
このコードに正規表現による置換を適用して、setter
を生成してみます。
sed
でやる場合、以下のようなコマンドになります。
echo "void set_account_id(string account_id)" | sed -E 's/(.*)(.*)\((.*) \2\)/\3 get_\2\(\)/'
では、sed
の置換部分s/(.*)(.*)\((.*) \2\)/\3 get_\2\(\)/
に注目して考えて見ます。
まずは、パターンにマッチさせるための、前方の(.*)(.*)\((.*) \2\)
の部分です。
関数名と引数名に同じパターンがありますね。繰り返しの部分は.*
とキャプチャ\2
を組み合わせて表現できます。
パターンの中に(.*)
が3つありますが、それぞれ以下の文字列がキャプチャされています。
(.*)(.*)
という正規表現をみると、一見「どこからどこまでキャプチャされているの?」と分からなくなります。
しかし後方に\2
があることによって、正規表現のエンジンが繰り返しのパターンがあることを知ります。よって、正規表現のエンジンは(.*)(.*)
と\2
の整合性を取るようにキャプチャします。
素晴らしいですね!
例えば、vscodeを使っていれば正規表現の置換を使って次のように似たようなコードの生成が一気にできます。
※vscodeの置換機能では、キャプチャした文字列は$n
で参照するので注意してください。vscodevim経由の置換では\n
の記法が利用できます。
まとめ
今回は正規表現の「.+」とキャプチャを組み合わせて繰り返しを含むパターンを作る方法を見てきました。
正規表現は入力のバリデーションやプログラムでの置換として使う以外にも、プログラミング中やsed
を使ったデータの加工にも利用できます。
エディタを使う際、時々あえて正規表現を使ってみて慣れることで、ちょっとしたデータの加工にsed
を使ったり、コードの生成を効率良く行うような「使い捨ての処理」を書くことができるようになります。
その積み重ねで、時間がかかっていたタスクを一瞬で片付けるための引き出しが増えていきそうですね!!