こんにちは!開発現場で日々、コードと格闘お疲れ様です。
今日は、VB.NETでの「正規表現(System.Text.RegularExpressions)」を使った文字列パターンのマッチングと、入力値検証(バリデーション)の極意についてお話ししますね。
Excelのマクロ(VBA)で「`InStr`関数や`Like`演算子を使って、何重もの`If`文でメールアドレスや型番をチェックしていた…」なんて経験はありませんか?
「あっちの文字が入っていたら、こっちはダメで…」と条件分岐を重ねるうちに、コードが読めない魔窟になってしまう、というのはよくある話です。
でも、安心してください。VB.NETが持つ`System.Text.RegularExpressions`名前空間を使いこなせば、複雑怪奇な文字列チェックも、たった数行の美しいコードで、しかも爆速で処理できるようになります。
ここをクリアすれば、あなたのVB.NETスキルは一段上のステージに到達しますよ。さあ、一緒に扉を開けていきましょう!
—
1. なぜ「正規表現」なのか?(VBAの限界を超える)
VBAの`Like`演算子でも簡単なワイルドカード検索はできますが、「半角英数のみ」「特定の桁数」「ドメインのルール」といった複雑な条件を組み合わせようとすると、途端に表現力が不足します。
正規表現(Regular Expressions)とは、いわば「文字列のパターンを記述する専用の超強力なミニ言語」です。
- 「英字から始まり、数字が3桁続き、末尾にハイフンと2桁の数字がある型番」
- 「厳密なルールに則ったメールアドレス」
これらの一見複雑な条件も、正規表現のパターンの文字列にギュッと凝縮して、一撃で判定させることができます。
—
2. VB.NET正規表現の基本と「3大クラス」
VB.NETで正規表現を扱うときは、`System.Text.RegularExpressions`(通称 `Regex`)という名前空間を使用します。まずは、絶対に押さえておくべき3つの主役を覚えましょう。
1. `Regex` クラス
- 正規表現エンジンの本体です。パターンをコンパイルしたり、マッチ判定を行ったりする主役中の主役。
2. `Match` クラス
- マッチングを行った結果(ヒットした情報)を格納するオブジェクト。
3. `MatchCollection` クラス
- 文字列の中から「ヒットしたものが複数あった場合」のコレクション(のっとりリストのようなもの)です。
💡 先輩エンジニアからの極意:`Regex`は「使い回せ」!
正規表現を使うとき、ついつい毎回 `System.Text.RegularExpressions.Regex.IsMatch(text, pattern)` と書いてしまいがちですが、ループ内でこれをやると、毎回パターンを解析するオーバーヘッド(無駄なコスト)が発生し、処理が重くなります。
パフォーマンスを極める現場では、`Regex`オブジェクトを事前に生成(または `Shared` で保持)し、それを使い回すのが鉄則です。
—
3. 実践!現場で使えるバリデーション実装例
それでは、コピペしてそのまま使える実用的なサンプルコードを見ていきましょう。
今回は、「型番」「郵便番号」「メールアドレス」という、実務で本当によく遭遇する3つのパターンを用意しました。
Imports System.Text.RegularExpressions
Public Module RegexValidationSample
‘ 【極意】Regexオブジェクトは一度生成して使い回すことで、パフォーマンスを最大化する!
‘ パターンが定数であれば、ReadOnlyなフィールドとして保持するのがプロの技です。
‘ 1. 型番パターン: アルファベット大文字2文字 + ハイフン + 数字4桁 (例: AB-1234)
Private ReadOnly PartNumberRegex As New Regex(“^[A-Z]{2}-\d{4}$”, RegexOptions.Compiled)
‘ 2. 郵便番号パターン: 3桁 + ハイフン + 4桁 (例: 123-4567)
Private ReadOnly ZipCodeRegex As New Regex(“^\d{3}-\d{4}$”, RegexOptions.Compiled)
‘ 3. メールアドレスパターン: RFCの厳密すぎない、実用的な判定用
Private ReadOnly EmailRegex As New Regex(“^[\w\.-]+@([\w-]+\.)+[\w-]{2,4}$”, RegexOptions.Compiled)
Public Sub Main()
‘ テスト用の入力値リスト
Dim testInputs As String() = {
“AB-1234”, ‘ 正常な型番
“ab-1234”, ‘ ✗ 小文字が含まれているのでNG
“123-4567”, ‘ 正常な郵便番号
“12-34567”, ‘ ✗ 桁数が違うのでNG
“test.user@example.co.jp”, ‘ 正常なメール
“invalid-email@” ‘ ✗ 形式が崩れているのでNG
}
Console.WriteLine(“=== 入力値バリデーションテスト開始 ===”)
For Each input As String In testInputs
Console.WriteLine(vbCrLf & $”検証対象: [{input}]”)
‘ 型番チェック
If PartNumberRegex.IsMatch(input) Then
Console.WriteLine(” -> 【型番】として有効です。”)
End If
‘ 郵便番号チェック
If ZipCodeRegex.IsMatch(input) Then
Console.WriteLine(” -> 【郵便番号】として有効です。”)
End If
‘ メールアドレスチェック
If EmailRegex.IsMatch(input) Then
Console.WriteLine(” -> 【メールアドレス】として有効です。”)
End If
Next
Console.WriteLine(vbCrLf & “=== テスト終了 ===”)
End Sub
End Module
—
4. コードの解説:正規表現の暗号を解読する
サンプルコードで使われている正規表現のパターンの意味を、パーツごとに分解して優しく解説します。ここさえ分かれば、どんなパターンも自力で組めるようになりますよ。
① 型番パターン: `^[A-Z]{2}-\d{4}$`
- `^` : 文字列の「先頭」を意味します(ここから始まること)。
- `[A-Z]` : アルファベットの「大文字AからZまで」の1文字を意味します。
- `{2}` : 直前の要素(ここでは `[A-Z]`)が「ちょうど2回連続する」ことを示します。
- `-` : そのままハイフン文字です。
- `\d` : 「数字(0〜9)」の1文字を意味します(`[0-9]`と同義)。
- `{4}` : 直前の要素(`\d`)が「ちょうど4回連続する」ことを示します。
- `$` : 文字列の「末尾」を意味します(ここで終わること)。
- 💡 `^` と `$` で囲むことで、「部分一致」ではなく「完全一致(余計な文字が含まれていないか)」を厳密にチェックできます。
② 郵便番号パターン: `^\d{3}-\d{4}$`
- `^\d{3}` : 先頭から3桁の数字。
- `-` : ハイフン。
- `\d{4}$` : 4桁の数字で終わり。
- 非常にシンプルですね!
③ メールアドレスパターン: `^[\w\.-]+@([\w-]+\.)+[\w-]{2,4}$`
少し複雑に見えますが、メールアドレスの構造(`ユーザー名 @ ドメイン名`)に分解できます。
- `[\w\.-]+` : ユーザー名部分。英数字・アンダースコア(`\w`)、ドット(`.`)、ハイフン(`-`)が1文字以上続く。
- `@` : アットマーク。
- `([\w-]+\.)+` : サブドメインやドメイン名(`example.` など)が1回以上繰り返される構造。
- `[\w-]{2,4}$` : 末尾のドメイン部分(`jp`, `com`, `co.jp` の `co` など)が2〜4文字であること。
—
5. 初学者が陥りやすい「3大罠」と回避策
最後に、現場でVB.NETを書き始めたエンジニアが必ずと言っていいほどハマる「罠」と、その回避策をお伝えします。
罠1:バックスラッシュ(`\`)の扱いで迷う
VB.NETの文字列内では、エスケープ文字としてバックスラッシュ(`\` または環境によっては円マーク `¥`)が使われます。正規表現で `\d` と書くつもりが、文字列表記でコンパイルエラーになったり、意図しない挙動になることがあります。
- 回避策: パターン文字列の先頭に `@` をつけるか(C#の場合)、VB.NETでは普通に `”\d{3}”` と書けばOKですが、ダブルクォーテーションの扱いに注意してください。VB.NETでは通常の文字列リテラル内で `\` はそのまま文字として扱われるため、過度に恐れる必要はありません(ただし `””` のエスケープなどは基本通りです)。
罠2:部分一致に気づかず、バグを見逃す
`Regex.IsMatch(“AB-1234-EXTRA”, “^[A-Z]{2}-\d{4}$”)` を実行すると、結果は `False` になります(`$` で終わる指定をしているため)。
しかし、もし `^` と `$` を付け忘れて `[A-Z]{2}-\d{4}` だけにしてしまうと、余分なゴミデータ(`-EXTRA`)が後ろにくっついていても `True` と判定されてしまいます。
- 回避策: 入力値検証(バリデーション)を行うときは、原則として `^`(先頭)と `$`(末尾)で挟んで完全一致を強制する 癖をつけましょう。
罠3: 例外処理(ArgumentException)の不備
存在しない不正な正規表現パターン(例えば閉じられていないカッコ `(abc` など)をコード内にハードコーディングすると、プログラム起動時や実行時に `ArgumentException` が発生し、アプリがクラッシュします。
- 回避策: パターンは必ずテストし、動的な文字列を正規表現のパターンとして組み立てる場合は、`Regex.Escape` メソッドを使ってエスケープ処理を安全に行うように心がけましょう。
—
まとめ
いかがでしたでしょうか?
VB.NETでの正規表現は、正しく怖がらずに使えば、あなたのコードを劇的にスマートにし、堅牢な入力値検証システムを構築するための最強の武器になります。
- `System.Text.RegularExpressions`名前空間をインポートする
- `Regex`オブジェクトは使い回してパフォーマンスを落とさない
- バリデーションでは `^` と `$` で完全一致させる
ここさえ押さえておけば、もう文字列操作で頭を抱える必要はありません。
ぜひ明日の開発現場から、このテクニックを取り入れてみてくださいね。あなたのVB.NETライフを応援しています!
