【入門編】【実務中級者向け】FSOとRegExpを連携させたテキスト内のメールアドレス・IPアドレス抽出&重複除外抽出 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク
スポンサーリンク

ログの混沌を制する:FSO・RegExp・Dictionaryで実現する「極限のデータ抽出術」

こんにちは。現場の自動化を支えるエンジニアの皆さん。
日々の業務で、膨大な量のログファイルやテキストデータに囲まれて、「この中から特定のIPアドレスだけを抜き出して、重複を消したリストが欲しい……」なんて、途方に暮れたことはありませんか?

「マクロの記録」や、単純な「文字列の検索」の段階を卒業し、一歩上の「自動化エンジニア」へとステップアップするためには、バラバラの機能を組み合わせて、一つの「パイプライン(処理の流れ)」を作るスキルが必要になります。

今日は、VBScriptにおける最強の三種の神器、FSO(ファイル操作)、RegExp(正規表現)、そしてDictionary(連想配列)を連携させ、大量のデータから必要な情報だけをクリーンに抽出する、プロの実践的な技法を伝授します。

ここをマスターすれば、あなたのVBScriptは単なる「スクリプト」から、強力な「ツール」へと進化しますよ。さあ、一緒に見ていきましょう。

1. 今回構築する「抽出パイプライン」の設計図

いきなりコードを書く前に、エンジニアとして最も大切なこと。それは「設計」です。
今回、私たちが作るのは以下のような「情報の流れ」を持つプログラムです。

1. 【入力層:FSO】:ファイルシステムを介して、巨大なテキストファイルを一行ずつ読み込む。
2. 【解析層:RegExp】:読み込んだ一行の中から、正規表現のパターンを使って「メールアドレス」や「IPアドレス」を炙り出す。
3. 【整理層:Dictionary】:見つかった情報をDictionaryに放り込む。Dictionaryの「キーの重複を許さない」という特性を利用して、自動的に重複を排除する。
4. 【出力層:FSO】:整理されたクリーンなリストを、新しいファイルとして書き出す。

この「読み込み $\to$ 解析 $\to$ 整理 $\to$ 書き出し」という流れは、データ処理の基本中の基本です。

2. 武器となる「三種の神器」の役割を知る

実装に入る前に、今回使うオブジェクトの「本質」を理解しておきましょう。

① FileSystemObject (FSO) :「手」の役割

ファイルを開き、読み、書き込む。物理的なファイル操作を司ります。
プロの視点: 大容量ファイルを扱うときは、`ReadAll`(一括読み込み)ではなく、`ReadLine`(一行ずつ読み込み)を使いましょう。一括読み込みはメモリを食いつぶし、システムを不安定にする原因になります。

② RegExp (Regular Expression) :「目」の役割

複雑な文字列パターンを瞬時に見つけ出す、超高性能な「目」です。
「数字が3つ、ドット、数字が3つ……」といったルールを、たった一行のパターンで記述できます。

③ Dictionary :「脳」の役割

「名前(Key)」と「値(Item)」をセットで管理する高度なメモリ空間です。
ここが重要! Dictionaryは、「同じキーを二度登録しようとすると、エラーになる(または上書きされる)」という性質を持っています。これを利用すれば、コードを複雑に書かなくても、一瞬で重複排除が完了します。

3. 実践:究極の抽出スクリプト

それでは、実際に動作するコードを見てみましょう。このコードは、そのままコピーして `.vbs` ファイルとして保存すれば動作するように設計しています。

' ==========================================================================
' Script Name: LogExtractorPro.vbs
' Description: FSO, RegExp, and Dictionary to extract IP/Email and remove duplicates.
' Author: Legend Architect
' ==========================================================================

Option Explicit

' --- 設定エリア ---
Const INPUT_FILE  = "C:\temp\access_log.txt"  ' 解析対象のログファイルパス
Const OUTPUT_FILE = "C:\temp\extracted_list.txt" ' 結果を出力するファイルパス

' --- メイン処理 ---
Main

Sub Main()
    Dim fso, ts, line, dict, regExp, matches, match
    Dim ipPattern, emailPattern
    
    ' オブジェクトの生成
    Set fso     = CreateObject("Scripting.FileSystemObject")
    Set dict    = CreateObject("Scripting.Dictionary")
    Set regExp  = CreateObject("VBScript.RegExp")
    
    ' 入力ファイルの存在チェック
    If Not fso.FileExists(INPUT_FILE) Then
        MsgBox "エラー: 入力ファイルが見つかりません。" & vbCrLf & INPUT_FILE, vbCritical
        Exit Sub
    End If

    ' --- 正規表現パターンの設定 ---
    ' IPアドレスのパターン (例: 192.168.1.1)
    ipPattern = "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"
    ' メールアドレスの簡易パターン
    emailPattern = "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"

    ' RegExpオブジェクトの設定
    regExp.Global = True      ' 見つかったものすべてを抽出
    regExp.IgnoreCase = True ' 大文字小文字を区別しない

    ' --- ファイル読み込みプロセス ---
    On Error Resume Next ' エラーハンドリングの開始
    Set ts = fso.OpenTextFile(INPUT_FILE, 1) ' 1 = ForReading
    
    If Err.Number <> 0 Then
        MsgBox "ファイルを開けませんでした: " & Err.Description, vbCritical
        Exit Sub
    End If
    On Error GoTo 0 ' エラーハンドリングを元に戻す

    Do Until ts.AtEndOfStream
        line = ts.ReadLine ' 一行ずつ読み込む(メモリに優しい!)

        ' 1. IPアドレスの抽出
        regExp.Pattern = ipPattern
        Set matches = regExp.Execute(line)
        For Each match In matches
            ' Dictionaryに登録(既に存在すれば何もしない)
            If Not dict.Exists(match.Value) Then
                dict.Add match.Value, ""
            End If
        Next

        ' 2. メールアドレスの抽出
        regExp.Pattern = emailPattern
        Set matches = regExp.Execute(line)
        For Each match In matches
            If Not dict.Exists(match.Value) Then
                dict.Add match.Value, ""
            End If
        Next
    Loop
    ts.Close

    ' --- 結果の書き出しプロセス ---
    Set ts = fso.CreateTextFile(OUTPUT_FILE, True) ' True = Overwrite
    
    Dim key
    For Each key In dict.Keys
        ts.WriteLine key ' 重複排除済みのKeyを一行ずつ書き出す
    Next
    ts.Close

    ' --- 後片付け(オブジェクトのライフサイクル管理) ---
    ' 参照を解除してメモリを解放する。これはプロの作法です。
    Set ts = Nothing
    Set dict = Nothing
    Set regExp = Nothing
    Set fso = Nothing

    MsgBox "抽出が完了しました!" & vbCrLf & "出力先: " & OUTPUT_FILE, vbInformation
End Sub

4. 陥りやすい罠:エンジニアが直面する「3つの壁」

このスクリプトを動かす際、あるいは自分で改造する際に、初心者が必ずと言っていいほどぶつかる壁があります。

壁その1:正規表現の「欲張り」問題

正規表現は強力すぎるゆえに、意図しない部分まで拾ってしまうことがあります。
例えば、IPアドレスのパターンを `\d+\.\d+\.\d+\.\d+` と書くと、`1234.5678.9.0` のような不正な形式まで拾ってしまう可能性があります。
今回のコードでは `\b` (Word Boundary:単語の境界) を使っています。これにより、「数字の塊の前後が区切られていること」を保証し、誤検知を減らしています。

壁その2:メモリ管理と「オブジェクトの解放」

VBScriptはガベージコレクション(不要なメモリを自動で掃除する仕組み)を持っていますが、大規模なループの中でオブジェクトを大量に生成したり、開きっぱなしにしたりすると、動作が目に見えて重くなります。
スクリプトの最後で `Set obj = Nothing` を行う習慣をつけてください。これは「私はこのオブジェクトをもう使いませんよ」という、OSへの礼儀なのです。

壁その3:文字コードの壁

ログファイルが `UTF-8` で、VBScriptの標準的な `OpenTextFile` が `Shift-JIS` を想定している場合、日本語が含まれていると文字化けします。
もし文字化けが発生した場合は、`ADODB.Stream` という別のオブジェクトを使い、文字コードを指定して読み込む手法に切り替える必要があります。これは「中級者への入り口」となる次のトピックです。

5. まとめ:ここをクリアすれば、基本はバッチリです

今回の技法を整理しましょう。

  • FSO でファイルを「一行ずつ」安全に読み込む。
  • RegExp で複雑なパターンを「鮮やかに」抜き出す。
  • Dictionary で重複を「スマートに」排除する。

この3つを組み合わせる手法は、ログ解析だけでなく、設定ファイルの書き換え、大量のファイル名の一括変更、データの集計など、あらゆる業務自動化に応用できます。

最初は正規表現のパターンを覚えるのが大変かもしれません。でも、焦らなくて大丈夫ですよ。一度「仕組み」を理解してしまえば、あとはパターンを使い回すだけです。

さあ、次は自分の手で、もっと複雑なパターンに挑戦してみてください。その一歩が、あなたを真の自動化エンジニアへと導いてくれるはずです。応援していますよ!

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