テキストを整形する

INPUT · スライド

違いを出す(`diff`)

01 / 07

「どこが違うの?」に答える道具

この章の最後は diff だよ。2つのファイルの違いを出す道具だね。

こういう場面で使うよ。

  • 設定ファイルを直した。どこを変えたんだっけ?
  • 動いていたときの控えと今のもの、何が違う?
  • 2つの名簿、どちらにしかいない人は誰?

目で見比べるのは大変だし、見落とすよね。diff なら違うところだけを教えてくれるんだ。

02 / 07

-+ で読む

a.txtb.txt を比べてみるよ。

~ $ diff a.txt b.txt--- a.txt+++ b.txt@@ -1,3 +1,3 @@ ringo-mikan+budou banana

読み方はこうだよ。

行の頭意味
(空白)両方にある(変わっていない)
-1つ目にだけある(消えた)
+2つ目にだけある(増えた)

つまり「mikanbudou に変わった」と言っているんだ。

--- a.txt+++ b.txt は、どちらが - でどちらが + かの説明だよ。- は左、+ は右だね。

03 / 07

@@ は場所を表す

@@ -1,3 +1,3 @@ という行が気になるよね。これはどのあたりの話かを表しているよ。

@@ -1,3 +1,3 @@     ↑     ↑   1つ目の  2つ目の  1行目から3行分

大きなファイルでは、違うところだけを抜き出して見せてくれるんだ。そのとき「これは何行目付近の話です」と教えてくれるのが @@ の行だよ。

この形は unified 形式(統一形式)と呼ばれていて、git diff やソフトウェアの修正パッチもまったく同じ形だよ。

ここで読めるようになっておくと、ずっと役に立つからね。プログラムの変更を人に見てもらうとき、必ずこの形で見せるんだ。

04 / 07

同じときは何も言わない

a.txtc.txt は中身が同じだよ。

~ $ diff a.txt c.txt~ $

何も出ないね。grepfind と同じで、「言うことが無い = 問題なし」だよ。

はっきり言ってほしいときは -s を付けるよ。

~ $ diff -s a.txt c.txtFiles a.txt and c.txt are identical

逆に、中身は見せずに「違うかどうか」だけ知りたいときは -q だね。

~ $ diff -q a.txt b.txtFiles a.txt and b.txt differ

大きなファイルで、違いの中身より「同じか違うか」だけが知りたいときに便利だよ。

05 / 07

終了ステータスで判断できる

diff は結果を終了ステータスでも教えてくれるよ。

ステータス意味
0同じ
1違う

直前の終了ステータスは $? で見られるよ。

diff a.txt b.txt; echo "code=$?"

これが便利なのは、プログラムから使えることだよ。人が目で見るのではなく、機械が判断できるんだ。

if diff -q a.txt b.txt > /dev/null; then  echo 同じelse  echo 違うfi

この if の書き方は章11でやるよ。いまは「diff は答えを数でも返す」と知っておいて。自動で見張る仕組みは、これで作れるんだ。

06 / 07

見えない違いも見つける

diff目に見えない違いも見つけてくれるよ。

d.txta.txt とほとんど同じだけれど、1行目の末尾に空白が2つ入っているんだ。

~ $ diff a.txt d.txt@@ -1,3 +1,3 @@-ringo+ringo mikan banana

-ringo+ringo同じに見えるのに違いとして出たね。末尾の空白は目に見えないからだよ。

これは「見た目は同じなのに動かない」という不具合の原因になるよ。だから diff が教えてくれるのは親切なんだ。

空白の違いを無視したいときは -b を付けるよ。

diff -b a.txt d.txt    # 何も出ない

07 / 07

さあ、打ってみよう

ファイルは5つだよ。

  • a.txtringomikanbanana
  • b.txtringobudoubanana(真ん中が違う)
  • c.txta.txt同じ
  • d.txta.txt と同じに見えるが1行目の末尾に空白
  • e.txta.txtkaki を足したもの

どれを比べるかで結果が変わるので、順番に試してみよう。

diff A B の順番は大事だよ。入れかえると -+ が逆になるからね。「前 → 後」の順に書く、と決めておくと混乱しないよ。