文字列の途中の不要な文字列を正規表現で検知して消してみる

こんにちは。くろはです。 今回は意外と使う場面のありそう(個人的な感想)な”文字列途中の可変な不要箇所を正規表現を用いて消す”ということについて書こうかと思います。

背景


私はDBを操作する際のGUIアプリケーションとしてHeidiSQLというアプリケーションを使用しています。
HeidiSQLは単一テーブルから抽出したレコードをInsert文の形式でエクスポートできる機能があるため、
時々この機能を利用して開発環境からマスタデータをローカル環境に移してきて開発を行っています。
ただしここでそのままInsert文を実行してしまうと主キーとなっているID列が開発環境の状態のままテーブルに格納されてしまいます。
たいていは気にしなくてもよいのですがローカル環境も元々はいつぞやの時点の本番環境をコピーしたものなので開発環境のIDをそのまま使うと
自分の行っている改修とは無関係な動作を引き起こしかねない(=正しい結果が得られない)ことにつながるパターンがあったりします。
そこでid列を指定せずにレコードを挿入するとテーブル定義上は連番でIDを振ってくれるのでinsert文からID列と値の指定箇所を消してから挿入、といった作業を時々しています。
10行くらいなら「まぁ手作業でもよいか…」となりますがさすがにそれ以上は労力が見合ってくれません。 というわけで表題の正規表現で一気に指定箇所を置換してしまおうと思った次第です。

結論

このようなSQLが複数あったとしてID列とその値を1度に消します。
INSERT INTO `テスト` (`id`, `○○`, `△△`,`□□□`) VALUES (4401241, 'hoge', 'huga', 'hogehoge');
置換前と置換後の正規表現です。 置換前 (.+)id,(.+) VALUES ([0-9]*,(.+) 置換後 $1$2 VALUES ($3 置換した後のSQLは次のように変更されます。 このようなSQLが複数あったとしてID列とその値を1度に消します。
INSERT INTO `テスト` (`id`, `○○`, `△△`,`□□□`) VALUES (4401241, 'hoge', 'huga', 'hogehoge');
置換前と置換後の正規表現です。 置換前 (.+)id,(.+) VALUES ([0-9]*,(.+) 置換後 $1$2 VALUES ($3 置換した後のSQLは次のように変更されます。  
INSERT INTO `テスト` (`○○`, `△△`,`□□□`) VALUES ('hoge', 'huga', 'hogehoge');
無事ID列と値だけが消えました。  

考え方

正規表現における記号の意味等は割愛しますが置換前のパターン構造を文字で解説すると、 【文頭からidまでの任意の文字の繰り返し】 + 【`id`,】 + 【id,からVALUESまでの任意の文字の繰り返し】+【VALUES ( 【0~9の任意の数字の繰り返し+「,」】】+ 【以降文末までの任意の文字の繰り返し】 という感じです(逆に複雑か….?) 正規表現では”()”でくくると1つのグループとして評価されます。(=文字列とは判定されない) そのため「VALUES ( 」 として「 ( 」をエスケープしてあげないと正しくパターンを判定できません。 置換後の正規表現は結構シンプルで 【1つ目のグループに含まれる文字列】+【2つ目のグループに含まれる文字列】+【VALUES (】+ 【3つ目のグループに含まれる文字列】 というパターン構造になっています。 置換前のパターンの箇所で「”()”でくくるとグループとして評価されます」と書きましたが”()”にはもう一つ、後方参照という役割があります。 後方参照とはざっくりというとカッコ内のパターンに合致する文字列を記憶し、パターン内の変数の値として該当する文字列を返してくれます。 置換後の正規表現パターンの$1~$3がその変数にあたります。 これにより変更が不要な文字列をそのまま元の文字列から持ってくることができます。 青線が今回削除した部分、赤線がかっこでくくったり文字列をそのまま指定して新しく作る文字列として指定している部分です。こうやった方が分かりやすかったかも。 今回はIDの値にあたる部分がVALUES ( の後に来る文字列だったためVALUES ( をわざわざべた書きでパターンとしたけどもっと簡潔に書けたかもしれないと思えてきました。話が脱線しそうなので今回はここまでです。

終わりに

改めて見返すと正規表現のパターンの書き方って難しいけどどうパターンを組むかというのがパズルのようで楽しかったりするんですよね。ただカッコでネストしまくるとあっという間に迷宮の出来上がりなのでできるだけ簡潔に書けるように普段から意識していきたいですね。