WinMergeの比較処理前に正規表現フィルタのプラグインで差分を無視したいテキストを定義する

[WinMerge (日本語版)](https://winmergejp.bitbucket.io/)、便利ですよね。(最近もっぱらVSCodeのcompare機能使ってるけど…)

で、最近仕事で「Tera Termの作業ログをdiffしたいけど、行の頭にタイムスタンプついてるから単純比較できない」と小耳に挟んだのですが、うーん、、まぁなんか適当なフィルタスクリプトかまして削ればいいのでは…とは思ったけど、割とプラグインが充実してるWinMerge単体でそんなフィルタ機能あるんじゃないかなと思い、探してみた。

ら、まさにそういうことを解決するプラグインが標準装備してた。

# 急いでる人向け

WinMerge(2.14.0-jp-152以降)の`PrediffLineFilter`フィルタプラグインに正規表現で比較処理前のフィルタ書ける。

[公式のアニメーションgifによる説明](https://winmergejp.bitbucket.io/demos/prediff-linefilter-plugin-demo.gif)
![公式のアニメーションgifによる説明](https://winmergejp.bitbucket.io/demos/prediff-linefilter-plugin-demo.gif)

# 例題

Tera Termのこのログ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/c831142e-50ed-d0e7-7e73-a77d4653ad83.png)

の、「タイムスタンプ」にチェックしてログ出力設定して

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/6c31bb91-b080-31bb-8ed5-31d4c6a9b45a.png)

こういう操作を行うと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/6c98b45b-0432-5e18-8dec-330fcd1319e1.png)

こんなログファイルが出力されます。

```

[2019-11-21 21:52:54.434] pwd
[2019-11-21 21:52:55.020] /home/zaki
[2019-11-21 21:52:55.020] [zaki@manager ~]$ id
[2019-11-21 21:52:56.263] uid=1000(zaki) gid=1000(zaki) groups=1000(zaki),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[2019-11-21 21:52:56.264] [zaki@manager ~]$ date
[2019-11-21 21:52:58.086] 2019年 11月 22日 金曜日 01:40:43 JST
[2019-11-21 21:52:58.088] [zaki@manager ~]$ hostname
[2019-11-21 21:53:05.237] manager.local.jp-z.jp
[2019-11-21 21:53:05.237] [zaki@manager ~]$ 
```

比較用に、全く同じ操作をして出力したログを用意します。

```

[2019-11-21 21:54:48.081] pwd
[2019-11-21 21:54:49.171] /home/zaki
[2019-11-21 21:54:49.171] [zaki@manager ~]$ id
[2019-11-21 21:54:50.404] uid=1000(zaki) gid=1000(zaki) groups=1000(zaki),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[2019-11-21 21:54:50.404] [zaki@manager ~]$ date
[2019-11-21 21:54:51.270] 2019年 11月 22日 金曜日 01:42:27 JST
[2019-11-21 21:54:51.270] [zaki@manager ~]$ hostname
[2019-11-21 21:54:52.995] manager.local.jp-z.jp
[2019-11-21 21:54:52.995] [zaki@manager ~]$ 
```

これで二つのファイルは

- 実行するコマンドは同じ
- コマンドの結果は`pwd`, `id`, `hostname`は同じ
- `date`の実行結果は異なる
- 行頭のタイムスタンプは異なる

という状態

# WinMergeで比較

当然ながら行頭のタイムスタンプが異なるので、全行差分アリとなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/0236c119-4670-c5c6-c8b9-d312f729aad1.png)

やりたいことは、この行頭のタイムスタンプ部分を無視して差分をチェックすること。
このサンプルログでいうと、`date`の実行結果が違うことを確認したい。

## PrediffLineFilterフィルタ

そこで使用するのが `PrediffLineFilter` プラグイン。
※ PrediffLineFilterプラグインは 2.14.0-jp-152 で追加されてるので、古いWinMerge使ってる人はアップデートしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/36e99c78-0f52-b430-41ab-d179d832acd6.png)

初期状態ではフィルタ設定は何も登録されてるので何も変化しません。

## PrediffLineFilterフィルタ設定

「プラグインの設定」から。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/3bec2971-96b2-547f-e36a-0c58b2999ae2.png)

「PrediffLineFilter.sct」を選択して「プラグインの設定(L)」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/1f290408-6769-156f-c0b9-d35e8f3af87c.png)

すると、ファイルのdiffを行う前に正規表現を使って文字列処理を行う設定画面が表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/099c929c-ffbd-c1e7-b649-c5a3fcbaa913.png)

もうおわかりですね。

ここに「行頭のタイムスタンプを削除する正規表現」を入れておけば、タイムスタンプ部分を無視して差分チェックができるようになります。

サンプルなので雑に「先頭(`^`)の`[`から、最初の`]`までを消去」するように、以下のように設定。

|設定|入力|
|---|---|
|大文字小文字の違い||
|正規表現を使用|✓|
|検索文字列|`^\[.*?\]`|
|置換後の文字列| (空白) |

こんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/ece1d77d-5237-0593-a905-97bdb71fe9f0.png)

これで[OK]して、プラグイン設定のダイアログも[OK]で抜けて、メイン画面の[プラグイン]->[比較前処理プラグイン]->[PrediffLineFilter.sct]にチェックが入った状態にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/1394477c-8264-08bf-93f8-a8df2f1ab90f.png)

すると、こんな風に、フィルタに設定した行頭のタイムスタンプ部分を無視(薄い色はついてるけど)して差分チェックが行われます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256859/e7abdb9a-1aad-1e20-0f36-541fdff5217c.png)

# 簡単正規表現の説明

`^\[.*?\]` を簡単に説明すると以下の通り

- `^` : 行頭を表すメタ文字
- `\[` : "["文字そのもの。`[`は正規表現の範囲指定のメタ文字(開始)なので、エスケープしてる
- `.` : 任意の一文字
- `*` : 直前の文字(ここで言うと↑の任意の一文字)の0回以上繰り返し
- `?` : 最短一致。 ↑の`.*`で任意の文字の繰り返しはデフォルトは最長一致で最も長くマッチしようとするので、↓の`]`が出てくるまで全部マッチしようとするので、__プロンプトの`[username@hostname dir]`の終端の`]`までマッチ__ してしまう。そこで、`.*?`とすることで、最初の`]`までしかマッチしないようにする
    - ちなみにこれは、`*`や`+`などの「繰り返し」に付加されるオプション
    - `?`単体で出現した場合は、`?`の左の文字が「0文字か1文字か(有るか無いか)」を表す。`zaki?`であれば、`zak`か`zaki`にマッチ
- `\]` : "]"文字そのもの。`]`は(中略)エスケープしてる

正規表現まとめもいちど書いておきたいな。。布教用に。

---

いま気付いたけど、このmanagerってサーバ、時計めっちゃズレてるな…

---

ちなみにみんなTera Termログって使ってます？
~~個人的には`script`コマンドで育ったので、`script`プラス`PS1`に時刻表示でもいいのではーとか思ってたりしますが。~~
「ネットワーク機器などで、ログを取得する環境が(`script`とかが使える)LinuxなOSとは限らない」とのコメントを頂きました。確かに……