Ubuntu Weekly Recipe

第328回 「違いがわかる人」になろう

この記事を読むのに必要な時間:およそ 6 分

人の世は移ろいゆくものです。人生の劇的な変化にはそうそう遭遇しないかもしれませんが,身の回りのちょっとした変化ぐらいであれば毎日のようにどこかで発生しています。そしてその違いに気が付けるかどうかで,世界を見る目は大きく変わるのです。

バージョンアップ前後のソースコードの差異,校正から戻ってきた原稿の変更点,ミステリーツアーを賭けた間違い探し,恋人の髪型の変化……。そんな日々の「違いがわかる人」になり,ゆくゆくは上質を知る人になるために,今回はいくつかの差分ツールを紹介します。

テキストの差分

Ubuntuの利用者が一番よく調べる「違い」はテキストデータ,とくにソースコードの「差分」でしょう。Ubuntuに最初から入っているdiffコマンドは,2つのファイルやディレクトリの差分を人と機械が読みやすいフォーマットで作成するためのコマンドです。

たとえば以下の2つのファイル,sampleA.txtとそれを校正したsampleB.txtが存在するとします。

sampleA.txt

Lorem ipsum dolor sit amet, consectetur adipiscing
elit. Sed pulvinor nulla vel purus dictum, vel
convallis eros pellentesque. Sed vulputate, massa
wq
id tempor ullamcorper, arku nunc cursus jsto, in
porttitor.

sampleB.txt

Lorem ipsum dolor sit amet, consectetur adipiscing
elit. Sed pulvinar nulla vel purus dictum, vel
convallis eros pellentesque. Sed vulputate, massa
id tempor ullamcorper, arcu nunc cursus justo, in
porttitor.

3個所ほど違いを仕込んであるのですが,わかりますでしょうか。見ただけですぐにわかる違いもありますし,ぱっとではわかりづらい部分もあります。これをdiffコマンドで比較してみましょう。

$ diff -u sampleA.txt sampleB.txt
--- sampleA.txt 2014-06-08 02:09:36.191824793 +0900
+++ sampleB.txt 2014-06-08 02:04:27.075837981 +0900
@@ -1,6 +1,5 @@
 Lorem ipsum dolor sit amet, consectetur adipiscing
-elit. Sed pulvinor nulla vel purus dictum, vel
+elit. Sed pulvinar nulla vel purus dictum, vel
 convallis eros pellentesque. Sed vulputate, massa
-wq
-id tempor ullamcorper, arku nunc cursus jsto, in
+id tempor ullamcorper, arcu nunc cursus justo, in
 porttitor.

実行結果の最初の2行が比較対象のファイルの情報,3行目は差分が発生した塊(Hunk)の場所を示す行番号です。今回はHunkは1つだけですが,差分がとびとびに存在する場合はHunkも複数出力されます。Hunkの中では各行の先頭の1文字が特別な意味を持っています。空白なら差分がないことを示し,⁠-⁠はsampleA.txtのみに存在する行を,⁠+⁠はsampleB.txtのみに存在する行を示します。

たとえばサンプルファイルの2行目はsampleA.txtとsampleB.txtで異なる内容であるため,⁠-⁠⁠+⁠が1つずつ表示されています。diffコマンドは行単位の比較なので,その行のどこか一部が違うだけで,行全体が違うと表示されるのです。目をこらせばどの文字が違うかわかるでしょう。

Hunk上の下から3行目(-wq)はsampleA.txtのみに存在する行です。新しい行が追加されることで,後ろの行番号がずれることになりますが,diffは賢いので最後の行は「同じ内容の行」と判断しています。

オプションに「-u」を付けているのは,⁠unified形式」で出力するためです。diffは,標準では「context形式」の差分を表示しますが,若干人間には読みづらいので,unified形式を使うほうが一般的です。他にも「-y」オプションで横に並べて表示したり,オプションで出力フォーマットを細かく調整することも可能です。

ソースコードであれば,⁠-p」オプションを付けると関数名も表示してくれます。⁠-b」「-w」で末尾の空白や空白の数の変化を無視することもできますので,必要に応じて細かく調整すると良いでしょう。

このように出力された差分データは,patchコマンドを使うことで適用できます。今回の例ですとほとんど恩恵はありませんが,テキストファイルに加えた変更を逐一「このファイルの何行目のこれをこう変更して」と言葉で伝えることなく「このパッチ(差分ファイル)を適用してください」の一言で済むのはとても便利です。今回紹介する差分ツールの中には,差分の適用機能まで持ったツールも多数存在します。

ここまでが差分ツールに関する基本的な話です。

diffコマンドの派生品

diffコマンドは変更履歴を確認できる非常に便利なツールであるため,その派生品や別実装,オプションなどが多数存在します。

たとえばdiffは1行ずつ比較するため,長い行のどこか一部が変更された場合,どこが変わっているか見付けるのは困難です。そんなとき単語ごとに比較するwdiffであれば,より簡単にどこが変わったか確認できます。

$ sudo apt install wdiff
$ wdiff sampleA.txt sampleB.txt
Lorem ipsum dolor sit amet, consectetur adipiscing
elit. Sed [-pulvinor-] {+pulvinar+} nulla vel purus dictum, vel
convallis eros pellentesque. Sed vulputate, massa
[-wq-]
id tempor ullamcorper, [-arku-] {+arcu+} nunc cursus [-jsto,-] {+justo,+} in
porttitor.

“[--]⁠が削除された単語,⁠{++}⁠が追加された単語です。ただしwdiffは半角空白を単語の区切りとして使用しているため,日本語の文章で使うには難があります。日本語文章の単語単位の差分を表示したい場合は,後ほど紹介するDocDiffを使うと良いでしょう。

他にもcolordiffコマンドを使えば差分を色付きで表示できますし,imediff2は差分を適用するかどうかをncursesを使ってグラフィカルに選択できます。またEmacsやVimなどは,エディタ自身が差分を生成し表示できます。

図1 vimdiffコマンド(もしくはvim -d)で差分を表示した例

図1 vimdiffコマンド(もしくはvim -d)で差分を表示した例

多様な出力フォーマットに対応するDocDiff

Ruby製のツールであるDocDiffは,HTMLをはじめとするいくつかの出力形式や日本語文字コードに対応した差分表示ツールです。

$ sudo apt install docdiff
$ docdiff --tty sampleA.txt sampleB.txt

図2 wdiffのように単語で区切りつつ,色分けして表示される

図2 wdiffのように単語で区切りつつ,色分けして表示される

図3 日本語を考慮した単語区切りにも対応している

図3 日本語を考慮した単語区切りにも対応している

「--tty」オプションを付けることで,他のdiffコマンドと同様に端末に出力できますし,HTMLや真鵺道と言った出力方式も選べます。標準では単語単位の差分ですが,⁠--line」「--char」オプションによって,行単位だけでなく文字単位での差分も出力できます。

図4 文字単位の差分をHTMLとして出力した例

図4 文字単位の差分をHTMLとして出力した例

人間による読みやすさを追求するのであれば,DocDiffは大変便利でしょう。

GUIで差分を表示する

GUIで比較しながら編集したいなら,Meldが便利です。Ubuntuのリポジトリからmeldパッケージをインストールすることで利用できます。背景色と前景色を変更することで,行単位と文字単位の比較を同時に行えます。左右のスクロールバーには,ファイル全体に対して差分が存在する場所に印がついているため,ファイル全体を俯瞰しつつ編集が可能です。

図5 GUIならではの表現により,どの行のどの部分が異なるかわかりやすい

図5 GUIならではの表現により,どの行のどの部分が異なるかわかりやすい

ディレクトリ同士を比較したり,バージョン管理システムのディレクトリを開いた場合は,変更点が存在する場所が強調表示されるファイラーとしても使えます。

Ubuntu 14.04 LTSまでのMeldパッケージはGTK+2版ではありますが,Utopic以降はGTK+3に対応した現在開発中の3.x系列が採用される予定です。

特定のファイル形式向け差分ツール

ファイルの中身を解析を解析したうえで,その差分を表示するツールもあります。たとえばtardiffはtarアーカイブを展開し,1つずつ差分を取ってその解析結果を表示しますし,latexdiffは2つのTeXファイルの差分を新たなTeXファイルとして出力するツールです。numdiffは,異なる数値表現を正規化したうえで,同じかどうかや異なっている場合はその数字の差を表示しますので,数値データファイルの比較を行う場合に便利でしょう。

著者プロフィール

柴田充也(しばたみつや)

Ubuntu Japanese Team Member。数年前にLaunchpad上でStellariumの翻訳をしたことがきっかけで,Ubuntuの翻訳にも関わるようになりました。

コメント

コメントの記入