【入門編】【高速キーワードフィルタ】FileSystemObject ReadLine と正規表現を組み合わせた超巨大ログからの対象行抽出 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは!日々の業務自動化、本当にお疲れ様です。マクロの記録を卒業し、「本格的なスクリプトで業務を効率化したい!」という素晴らしい一歩を踏み出したあなたへ。

今回は、現場でよくある「数十GBもある巨大なログファイルから、特定のエラー行だけを瞬時に抜き出したい」という実務直結のテーマを扱います。

「VBScriptで巨大ファイルを扱うと、すぐにメモリーエラーになる……」
そんな絶望を味わったことはありませんか? 大丈夫。メモリの仕組みと、オブジェクトのライフサイクルを正しく理解すれば、VBScriptは驚くほど軽快に巨大データを料理できるようになります。

ここをクリアすれば、あなたのVBScriptの基本はバッチリですよ。さあ、一緒にプロの領域へと進みましょう!

1. なぜ巨大ログの処理でメモリが枯渇するのか?

まず、初心者が陥りがちな「やってはいけない処理」からお話しします。

‘ 【NGパターン】絶対にやってはいけない全読み込み
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set file = fso.OpenTextFile(“C:\Logs\huge_log.txt”, 1)

‘ ReadAllを使うと、ファイルの全データが一気にメモリにロードされます
allText = file.ReadAll

‘ 数十GBのファイルをメモリに載せたら…当然こうなりますよね
‘ -> [エラー: メモリ不足です (Out of memory)]

VBScript(というかWindowsのスクリプト環境)において、数ギガバイトのテキストを一度に変数へ放り込むのは「自爆行為」です。OSのメモリを一瞬で食いつぶし、スクリプトは強制終了します。

解決の鍵:1行ずつ読む「ストリーミング処理」

これを解決するのが、「必要な分だけ少しずつ読み込む(ストリーム処理)」という考え方です。
水道の蛇口をイメージしてください。バケツに水を一気に入れる(`ReadAll`)のではなく、コップ1杯ずつすくいながら飲む(`ReadLine`)のです。これなら、何テラバイトのファイルであっても、メモリ消費量は常に一定(数キロバイト程度)に抑えられます。

2. 【極限最適化】FileSystemObject × 正規表現の黄金律

それでは、数十GBのログから秒速で特定のエラーコード(例:`ERR-503`など)を抽出する、プロ仕様のコードをお見せします。

デスクトップに `filter_log.vbs` という名前で保存し、中身を以下のように記述してみてください。

‘ =================================================================00
‘ 巨大ログ高速フィルタリング・スクリプト
‘ ターゲット:数十GBのログから特定キーワード(正規表現)を抽出
‘ =================================================================00
Option Explicit

Dim fso, targetFile, outputFile
Dim filePath, outPath, searchPattern
Dim lineCount, matchCount
Dim objRegEx, targetLine

‘ — 1. 設定エリア —
filePath = “C:\Logs\server_access.log” ‘ 読み込む巨大ログのパス
outPath = “C:\Logs\extracted_errors.txt” ‘ 抽出結果の出力先
searchPattern = “ERR-(404|500|503)” ‘ 抽出したいパターン(正規表現)

‘ — 2. オブジェクトの準備 —
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ ファイルの存在チェック
If Not fso.FileExists(filePath) Then
WScript.Echo “エラー: 指定されたログファイルが存在しません。”
WScript.Quit
End If

‘ 読み取り専用でファイルを開く (ForReading = 1)
Set targetFile = fso.OpenTextFile(filePath, 1, False)

‘ 書き込み用として出力ファイルを作成(存在する場合は上書き)
Set outputFile = fso.CreateTextFile(outPath, True)

‘ 正規表現オブジェクトの生成(使い回すことでパフォーマンスを極限まで高める)
Set objRegEx = New RegExp
objRegEx.Pattern = searchPattern
objRegEx.IgnoreCase = True 大文字小文字を区別しない
objRegEx.Global = True ‘ マッチ箇所をすべて探す

lineCount = 0
matchCount = 0

WScript.Echo “処理を開始します。しばらくお待ちください…”

‘ — 3. メモリ枯渇を防ぐ 1行ループ読込 (ReadLine) —
Do While Not targetFile.AtEndOfStream
targetLine = targetFile.ReadLine
lineCount = lineCount + 1

‘ 正規表現によるパターンマッチング
If objRegEx.Test(targetLine) Then
outputFile.WriteLine targetLine
matchCount = matchCount + 1
End If

‘ 10万行ごとに進捗をコンソールに表示(フリーズしていないことを確認するため)
If lineCount Mod 100000 = 0 Then
WScript.Echo lineCount & ” 行をスキャン完了…”
End If
Loop

‘ — 4. クリーンアップ(オブジェクトの解放) —
‘ 巨大なリソースを扱う時は、明示的に閉じ、メモリを解放するのがエンジニアの美学
targetFile.Close
outputFile.Close

Set objRegEx = Nothing
Set outputFile = Nothing
Set targetFile = Nothing
Set fso = Nothing

‘ — 5. 完了通知 —
WScript.Echo “処理が正常に完了しました!” & vbCrLf & _
“総スキャン行数: ” & lineCount & ” 行” & vbCrLf & _
“抽出ヒット数: ” & matchCount & ” 行” & vbCrLf & _
“出力先: ” & outPath

3. コードの重要ポイントと「知見」の解説

このコードには、現場で培ったパフォーマンス向上の知見がいくつも詰まっています。

① `AtEndOfStream` と `ReadLine` のコンビネーション

ファイルが終わり(EOF)に達するまで、1行ずつ変数に読み込みます。変数 `targetLine` はループのたびに上書きされるため、メモリがゴミ屋敷になることがありません。

② 正規表現(RegExp)オブジェクトの「ループ外生成」

初心者がやりがちなミスとして、「`Do While` ループの中で `New RegExp` を何度も呼ぶ」というものがあります。これをしてしまうと、ループの回数分だけメモリの確保と破棄が繰り返され、パフォーマンスが劇的に低下します。
オブジェクトはループに入る前に1回だけ生成し、使い回す。これが高速化の鉄則です。

③ 適切なリソースの解放(ライフサイクル管理)

処理が終わったら `.Close` でファイルを閉じ、`Set … = Nothing` でメモリをOSに返却します。VBScriptはスクリプト終了時に自動で解放してくれますが、巨大なファイルを扱う場合は、自らの手で確実かつ早期に解放する癖をつけましょう。

4. 陥りやすいエラーと対策

1. 「ファイルが見つからない(エラー 53)」

  • パスの指定ミス、またはファイル名に隠し文字やスペースが含まれている場合に起因します。`fso.FileExists` による事前チェックを必ず入れるようにしましょう。

2. 「書き込み権限がありません(エラー 70)」

  • 出力先フォルダ(例: `C:\Logs\`)に書き込み権限がない、あるいは別プロセス(テキストエディタ等)で `extracted_errors.txt` が開かれている場合に発生します。出力先はデスクトップなどの書き込み可能な場所に指定するのが無難です。

まとめ

いかがでしょうか?
「VBScriptなんて古い言語だ」と侮るなかれ。OSの標準機能だけで動作するWSH/VBScriptは、専用の環境構築すら不要で、サーバーのメンテナンスやローカルのログ解析において今なお最強の武器になります。

今回マスターした「ストリーム読み込み × 正規表現フィルタ」の技術は、VBA(Excelマクロ)や他のプログラミング言語(PythonやC#など)にステップアップしたときにも、そのまま通用する普遍的なアーキテクチャです。

日々の手作業や、フリーズする重いツールとは今日でサヨナラしましょう。ぜひ、あなたの現場でもこのスクリプトを役立ててくださいね!

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