0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

複数の正規表現パターンをログファイルに一括適用して行番号付きで抽出する

0
Posted at

背景

サーバーログの解析で「ERRORとWARNを同時に、行番号付きで抽出したい」というニーズに対し、VSCode標準の検索機能(Ctrl+F)は1パターンしか扱えず、行番号の記録も手動でした。複数パターン一括抽出マクロの実装ポイントを紹介します。

1. 選択範囲をパターンリストとして読み取る

function getSelectedPatterns(
    document: vscode.TextDocument,
    selection: vscode.Selection
): string[] {
    const patterns: string[] = [];
    for (let i = selection.start.line; i <= selection.end.line; i++) {
        const lineText = document.lineAt(i).text.trim();
        if (!lineText || lineText.startsWith('#') || lineText.startsWith('//')) {
            continue;
        }
        try {
            new RegExp(lineText);
            patterns.push(lineText);
        } catch (e) {
            vscode.window.showWarningMessage(`不正な正規表現をスキップ: ${lineText}`);
        }
    }
    return patterns;
}

複数行を選択した状態でマクロを実行すると、各行を1つの正規表現パターンとして扱います。#や//で始まる行はコメントとしてスキップし、new RegExp(lineText)が例外を投げた行(構文的に不正な正規表現)も自動的に除外することで、パターンリストをテキストファイルとして管理・再利用しやすくしています。

2. 全行を1回ずつスキャンして行番号付きで記録

for (const pattern of patterns) {
    const regex = new RegExp(pattern);
    const matchedLines: MatchedLine[] = [];
    for (let i = 0; i < document.lineCount; i++) {
        const line = document.lineAt(i);
        if (regex.test(line.text)) {
            matchedLines.push({ lineNumber: i + 1, text: line.text });
        }
    }
    matches.push({ pattern, lines: matchedLines });
}

document.lineAt(i)で1行ずつ取得しregex.test()で判定するだけの単純な実装ですが、行番号をi + 1(1-based)で保持しておくことで、抽出結果から元ファイルへCtrl+Gでジャンプする際に迷わなくなります。パターン数×行数のループになるため計算量はO(パターン数×行数)ですが、数千行程度のログなら体感上問題ありません。

3. 行番号の桁揃えで視認性を上げる

const maxLineNumber = Math.max(...match.lines.map(l => l.lineNumber));
const lineNumberWidth = String(maxLineNumber).length;

match.lines.forEach(matchedLine => {
    const lineNumberStr = String(matchedLine.lineNumber).padStart(lineNumberWidth, ' ');
    lines.push(`[Line ${lineNumberStr}] ${matchedLine.text}`);
});

マッチした行番号の最大値から桁数を求め、padStartで全行番号を右寄せに揃えることで、[Line 5]と[Line 389]のように出力が縦に整列します。小さな工夫ですが、大量の抽出結果を目視で追う際の可読性が変わります。

4. 出力は新規ドキュメントとして隣に開く

const doc = await vscode.workspace.openTextDocument({
    content: output,
    language: 'log'
});
await vscode.window.showTextDocument(doc, {
    viewColumn: vscode.ViewColumn.Beside,
    preview: false
});

ViewColumn.Besideを指定するだけで、元ファイルの隣のペインに抽出結果が開きます。元ファイルを一切変更せず、抽出結果は別ファイルとして保存できるため、調査の履歴を残しながら安全に作業できます。

まとめ

選択範囲を「パターンリスト」として解釈する発想と、行番号の記録・桁揃えによる可読性向上、この2点が実務で使えるログ抽出ツールにする上でのポイントでした。カンマ区切り入力への対応を含む完全なコードは元記事にまとめています。

→ 正規表現マッチ抽出を実現するTypeScriptマクロ(ブログ)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?