正規表現の勉強に欠かせない「正規表現テストツール」を自作!(第2回・ソースコード解説編)

プログラミング入門
この記事は約7分で読めます。

今回は、正規表現テストツールのソースコードについて解説します。

プロジェクト一式のダウンロード

プロジェクト一式は下記からダウンロードが可能です。

プロジェクトを任意のフォルダに解答の上、RegexTest.sln をダブルクリックするとVisual Studio 2019 が立ち上がり、ソースコードが表示されます。

ソースコードの解説

まず、使い方について簡単に操作方法について復習しておきましょう。

クラス構成

ソースコードを解説する前に、クラスの構成について簡単に触れておきたいと思います。

今回は画面のクラス(MainForm)の他、画面上のコントロールの値を保存/復元するための ControlValueManager クラスの2本立てになっています。

今回は1つのファイル(MainForm.cs)に2つのクラスを記述しましたが、他のプログラムで流用する事を考えるなら、別ファイル(例えば、ControlValueManager.cs)にしておく方が良いと思います。

ソースコード全体

今回は300行ちょっとのソースコード量になっています。

1つ1つのメソッドはそれほど難しい事をしていませんので、コメントと合わせて読み進めて頂ければ、どんなことをやっているか分かると思います。

System.Text.RegularExpressionsの記述

正規表現を使う場合は、System.Text.RegularExpressions名前空間をソースコードの冒頭に記述しておきます。

記述しない場合は、いちいち正規表現関連のクラスや列挙型(Enum)の前に名前空間を記述しなければならなくなるので面倒です。

FormLoadとFormCloseの処理

FormLoadでは次の4つのことを行っています。

  • プログラム起動におけるコントロールの初期設定
  • テキストボックスに対してドラッグ&ドロップの機能付加
  • ヘルプファイルの読み込み
  • コントロールの値の復元を行っています。

ControlValueManagerは、あらかじめ値の保存/復元をしたいコントロールを配列で宣言し、それをインスタンス生成時の引数として渡した後、Restoreメソッドを呼ぶという使い方になります。

以下がFormLoadのソースコードです。

一方、FormClose処理では、ControlValueManagerのRestoreメソッドを呼んで、コントロールの値をファイルに書き出しています。

実行ボタンクリック処理

ここでは、

  • 各種チェックボックスの状態から正規表現クラスのオプションを組み立てる。
  • 正規表現のソースコードを生成し、ソースコード欄に表示する。
  • 抽出/置換のラジオボタンの状態に応じて、Extractメソッド、Replaceメソッドを呼び分ける

という事をしています。

正規表現を使った抽出処理

ここでは、正規表現を使った抽出処理をメソッド化しています。

正規表現を使うには、Regrexクラスのインスタンスを生成する必要があります。

生成したインスタンスに対して、IsMachtメソッドを呼ぶと、一致する文字列が存在するかどうかがチェックできます。

また、Matchesメソッドを使う事で、一致する文字列をコレクションとして取得できます。

いちいちIsMatchメソッドで確認せずとも、いきなりMatchesメソッドを呼んで、コレクションのCountが0かどうかで判断するという方法もあります。

一致した文字列が格納されている MatchCollectionは、Match型として1つ1つ取り出すことができ、Match型のValueプロパティで一致した文字列が取得できます。

今回はForeachで1つづつ取り出し、改行で結合した結果を戻り値にしています。

正規表現を使った置換処理

抽出も置換も正規表現クラスのインスタンスを生成する部分は同じです。

インスタンスを生成した後は、Replaceメソッドを呼ぶだけで置換が行えます。

ドラッグ&ドロップ機能の付与

このメソッドは今までに何度も登場していますが、引数で指定したコントロールに対して、ドラッグ&ドロップの機能を付与するメソッドです。

ラムダ式を使ってイベントハンドラを記述することで、1つのメソッド内で完結させています。

単一行モードと複数行モードのチェック状態制御

単一行モードとは、対象となる文字列の改行を無視し、単一の文字列として扱うモードです。

一方複数行モードは、改行で区切られている事を前提にしたモードになります。

Regrexクラスのオプションでこれらを指定できるのですが、単一モードと複数行モードの両方を省略することは出来ても、両方にチェックを入れることは出来ません。

両方チェックを入れたからと言って特にエラーにはなりませんが、どちらが優先されるのか分からないので、片方にチェックが入った時、もう片方のチェックを外すという状態制御を行っています。

ラジオボタンを使うと、このような制御は必要ありませんが、単一行モードと複数行モードの両方を省略するという事が出来ないので、今回はあえてプログラムで制御しています。

ControlValueManagerクラス

ControlValueManagerクラスは次の様になっています。

コンストラクタの引数で渡したコントロール配列は、内部の_controls に格納されます。

Storeメソッド、Restoreメソッドが呼ばれる際、_controls配列からコントロールを取り出し、_variable にコントロール名とコントロールの値をセットします。

_variable はDataTableなので、Xml形式でファイルを読み書きするメソッド(ReadXmlとWriteXml)が備わっています。

今回は、このメソッドを使ってファイル保存/復元を行っています。

クラスのメンバ変数

クラスの冒頭で、クラス内で使う変数や定数を定義しています。

定数で TABLE、NAME、VALUE を定義していますが、これはDataTableの名前と列名になります。

FILE_PATH はファイルのパスですが、プログラムを実行した時のカレントフォルダ(EXEの場所)にファイルを置きたいので、”.\” をファイル名の先頭に付加しています。

また、DataTableの内容をファイル保存する時、DataTableに名前が無いとエラーになるため、ここで定数として定義してます。

NAMEとVALUEは列名なのでわざわざ定数定義する必要は無いという考えも有りますが、後に列名を変更する際、1か所修正するだけで済むように定数で定義しています。

コンストラクタ

コンストラクタでは、引数で渡されたコントロール配列を _controls に格納するとともに、DataTableのインスタンスを生成し、列を追加しています。

Storeメソッド

Storeメソッドでは、_control配列からコントロールを取り出し、Controlの型ごとに保存したい値を取り出し、DataTableに格納しています。

最初に _variable.Clear() で中身をクリアしていますが、これは Storeメソッドが複数回呼ばれた際、前の値が残っていてエラーになることを避けるためです。

全てのコントロールの処理が終わったら、最後に WriteXmlメソッドで保存しています。

Restoreメソッド

RestoreメソッドはStoreメソッドの逆で、ReadXmlメソッドでファイルから値を読み出した後、_control配列に登録されているコントロールを1つづつ取り出し、値を復元しています。

まとめ

以上でソースコードの解説は終わりです。

他のプログラムに流用しやすいよう、正規表現を使った抽出と置換はメソッド化し、コントロールの値の保存と復元はクラス化しています。

ちょっとした事ですが、このようなメソッドやクラスを使いまわすことで、使いやすいツールが作りやすくなります。

みなさんも色々なメソッドやクラスを作って、資産を増やしていきましょう。

タイトルとURLをコピーしました