やりたいこと
// 現状
Foo.builder()
.hoge("a")
.huga(10)
.build();
// こうしたい
new Foo("a", 10);
例としてJavaのコードを扱います。Builderパターン1をやめてコンストラクタでインスタンスを生成したいという設定です。
本記事はVSCodeで検証しました。(ツールによっては\n
に非対応ということもあるかもしれません。)
「現状」とマッチングする正規表現(シンプルなケース)
Foo\.builder\(\)[\s\S\n]*?build\(\);
(見やすさのために改行を入れると)
Foo\.builder\(\)
[\s\S\n]*?
build\(\);
正規表現2がどう働いているかというと、
-
Foo\.builder\(\)
で始まる部分を指定します。 -
[\s\S\n]
は改行コード含む全文字を示します3。 -
*?
は↑が0回以上繰り返されるパターン、その中で最小の文字列にヒットします。- つまり、↓のパターンが来るまでの任意の文字列(改行含む)です。
-
build\(\);
で終わる部分を指定します。(;
だけでも大丈夫です。)
ということです。
改行\n
を含めることで行を跨ぐことができます4。今回の例では末尾に;
が付くのでマッチングさせやすいですね。
これをnew Foo("a", 10);
に置換する事で目的を達成できます。
ただし、これだと"a"
や10
を変更できません。
複数箇所を修正する時に.hoge("b").huga(20)
が混ざっていたら少し辛いです。
代入部分をキャプチャして置換
# 検索欄
Foo\.builder\(\)[\s\S\n]*?hoge\((.*)\)[\s\S\n]*?huga\((.*)\)[\s\S\n]*?build\(\);
(見やすさのために改行を入れると)
Foo\.builder\(\)
[\s\S\n]*?
hoge\((.*)\)
[\s\S\n]*?
huga\((.*)\)
[\s\S\n]*?
build\(\);
# 置換欄
new Foo($1, $2);
// 前
Foo.builder()
.hoge("a")
.huga(10)
.build();
Foo.builder()
.hoge("b")
.huga(20)
.build();
// 後
new Foo("a", 10);
new Foo("b", 20);
[\s\S\n]*?hoge\((.*)\)
と [\s\S\n]*?huga\((.*)\)
というのが追加されています。
改行やインデントを挟むたびに[\s\S\n]*?
を入れます。また、hoge("a")
等のカッコの中身をキャプチャしています。
なお、hoge()
のように中身が空だとnew Foo(, 10);
のように不正な文ができます。
hoge("a)")
のようなケースだとキャプチャが上手く働きません(hoge\([^)]*\)
とやるといけるかもしれません)。
が、今回は考えません。疲れてきたからです。(「経験則上、これ以上やると費用が利益を上回りそうである」という意味の高度な専門用語です。)
いかがでしたか?
置換したい文が複数行を跨いでいると面倒ですよね。
正規表現を扱うたびにGoogleに正規表現 やり方
という何の面白みもないクエリを投げては経由させていただいたインターネットの諸々の通信機器に申し訳なく思う日々でしたが、この備忘録を書いたことによって負荷が改善されればと思います。
参考にさせていただいた文献については、続く脚注にて紹介いたします。
-
LombokのBuilderパターン解説
https://qiita.com/uhooi/items/bb817e7ca7dc128bf475 ↩ -
.Netにおける正規表現の仕様(厳密にはVSCodeとは違う仕様なので参考までに)
https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/regular-expression-language-quick-reference ↩ -
VS Codeで複数行に渡って正規表現を利用する
https://qiita.com/birdwatcher/items/dee34a11619b11e1fe81 ↩ -
2018年からVSCodeでmulti searchができるようになった
https://code.visualstudio.com/updates/v1_29#_multiline-search (リリースノート)
https://code-zen.hatenablog.com/entry/20210910/1631229389 (それを紹介する記事) ↩