【忘却のJava#3】sarの出力結果をExcelで扱いやすいように加工するプログラム

 数が少ないうちはいいのですが、複数のファイルを何回も繰り返しExcelに食わせたりしていると、その度に手動で加工するのが大変なので自動化します。
SIerさんはLinuxサーバから取得した情報って、どうせWindows環境でExcelでまとめるのでPowershellで全然問題ないのですが、あくまでJavaのお勉強ということで。

やりたいこと

sarの出力結果を加工して、Excelで扱いやすいようにする

加工対象とするsar出力結果

前回書いた「sarコマンドによるLinuxのリソース情報取得方法」のコマンドで取得できる情報を加工対象とします。

例:CPU情報(「sar -u 1 30 | egrep -v 'Average:'」の出力結果)

Linux 3.10.0-957.el7.x86_64 (localhost.localdomain)     04/06/2019      _x86_64_        (2 CPU)

05:28:12 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
05:28:13 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
05:28:14 AM     all      0.00      0.00      0.50      0.00      0.00     99.50
(~省略~)

05:28:34 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
05:28:35 AM     all      0.00      0.00      0.50      0.00      0.00     99.50
05:28:36 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
05:28:37 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
(~省略~)

05:28:56 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
05:28:57 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
05:28:58 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
05:28:59 AM     all      0.00      0.00      0.50      0.00      0.00     99.50
(~省略~)

これをtxt形式でプログラムから読み込むこととします。

どのように加工するのか

(1) 時刻のヘッダが時刻(「04:56:45 AM」みたいに)
 ⇒ヘッダの文字列を時刻ではなく"TIME"に置換する

(2)ヘッダ行(CPU %user ~)のとスペース行が繰り返し表示される
 ⇒先頭行のヘッダだけ残し、それ以外は削除する

上記はメモリもディスクもネットワークも共通的に加工可能です。

Javaコード

久しぶりにまともにコードを書きました。
ファイルを読み込んで上記の加工処理をして、別のファイルに書き込む感じです。
ひとまず動けばいいのでえいやーです。
Emacsで書いてみましたが、キーバインドを忘れまくっててショック・・・

import java.io.*;
import java.nio.file.*;
import java.util.regex.*;
import java.io.IOException;

class EditSar {
    public static void main(String args[]) {
        try {
            // 書き込み用のファイルを作成
            File outputfile = new File("./sar-cpu_after.txt");
            outputfile.createNewFile();
            Path outputpath = outputfile.toPath();

            // 読み込み用のファイルをオープン
            Path inputpath = Path.of("./sar-cpu_before.txt");
            String text = Files.readString(inputpath);
            BufferedReader reader = new BufferedReader(new StringReader(text));

            //処理開始メッセージ
            System.out.println("加工処理を開始しました。");

            // 読み込んだtxtファイルを1行ずつ処理
            int emptycnt = 0;
            Boolean nextempty = false;
            String line = null;
            while ((line = reader.readLine()) != null) {

                // 空行だったら、書き込まない
                if (line.isEmpty()) {
                    emptycnt++;
                    nextempty = true;
                } else {
                    // 空行の次の行(ヘッダ行)だったら、書き込まない
                    if (nextempty) {
                        nextempty = false;
                        // 最初のヘッダ行だけは書き込む
                        if (emptycnt == 1) {
                            String newline = null;
                            // 時刻を"TIME"という文字列に置換
                            newline = line.replaceAll("[0-9][0-9]:[0-9][0-9]:[0-9][0-9] [A-Z][A-Z]","TIME");
                            Files.writeString(outputpath, newline + "\r\n", StandardOpenOption.APPEND);
                        }
                    } else {
                        // 除外対象となっていない行を書き込む
                        Files.writeString(outputpath, line + "\r\n", StandardOpenOption.APPEND);
                    }
                }
            }
            reader.close();
            //処理終了メッセージ
            System.out.println("加工処理が終了しました。");

        } catch (IOException e) {
            System.out.println(e);
        }
    }
}

実行結果

[root@localhost 20190409_sar]# java EditSar
加工処理を開始しました。
加工処理が終了しました。

加工した結果 (sar-cpu_after.txt)

ヘッダを"TIME"に置換できました。
長くなるので省略していますが、繰り返しのヘッダも除外できてます。
あとはこれをExcelにtxtファイルとして読み込んで区切り位置を指定すればキレイに表にできます。
その後はピボットにするなり煮るなり焼くなり何なりと。

[root@localhost 20190409_sar]# cat sar-cpu_after.txt
Linux 3.10.0-957.el7.x86_64 (localhost.localdomain)     04/06/2019      _x86_64_        (2 CPU)
TIME     CPU     %user     %nice   %system   %iowait    %steal     %idle
05:28:13 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
05:28:14 AM     all      0.00      0.00      0.50      0.00      0.00     99.50
05:28:15 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
(~省略~)
05:29:08 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
05:29:09 AM     all      0.00      0.00      0.50      0.00      0.00     99.50
05:29:10 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
05:29:11 AM     all      0.00      0.00      0.00      0.00      0.00    100.00
05:29:12 AM     all      0.00      0.00      0.00      0.00      0.00    100.00


以上。