Pythonにはdifflibというモジュールがあり、これを用いると複数行のテキストデータどうしをdiff
コマンドのように比較し、同コマンドで得られるような形式で結果を得ることができる。
簡単な例として、ここではunified形式の差分を取ってみることにする。
比較対象の2つのテキストデータはそれぞれ文字列型のみを含むリストやタプルで、1つの行が1つの要素という形である必要がある。
["1行目", "2行目", "3行目"]
改行を含む複数行の文字列がある場合、そのメンバ関数splitlines()で分割したものが使える。
"""1行目
2行目
3行目""".splitlines()
difflib.unified_diff()の最初の2つの引数に、比較するテキストのリストやタプルをそれぞれ入れると、戻り値としてジェネレータが得られ、これをfor
文でループさせると結果を行単位で処理できる。
for line in difflib.unified_diff([入力1], [入力2]):
print(line)
3番目からの引数では差分の先頭のファイル名やタイムスタンプの部分に入る文字列を指定できるが、必須ではない。
“diffの差分形式比較 (unified, context, side-by-side, デフォルト, ed)” のデータを用いて、difflib.unified_diff()
を用いて比較してみることにする。
文字列のデータはスクリプトの中に記述している。
タイムスタンプ部分については、実際のタイムスタンプ値を用いたときの文字列への変換の参考として、適当な値を入れて表示している。
unifieddifftest.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import print_function
import difflib
import time
def main():
text1 = """あいうえお
かきくけこ
さしすせそ
たちつてと
なにぬねの
はひふへほ
まみむめも
やゆよ
らりるれろ
わをん
がぎぐげご
ざじずぜぞ
だぢづでど
ばびぶべぼ
ぱぴぷぺぽ
アイウエオ
カキクケコ
サシスセソ
タチツテト
ナニヌネノ
ハヒフヘホ
マミムメモ
ヤユヨ
ラリルレロ
ワヲン
ガギグゲゴ
ザジズゼゾ
ダヂヅデド
バビブベボ
パピプペポ"""
text2 = """あいうえお
かきくけこ
さしすせそ
たちつてと
なにぬねの
はひふへほ
まみむめも
やゆよら
りるれろ
わをん
ざじずぜぞ
だぢづでど
ばびぶべぼ
ぱぴぷぺぽ
アイウエオ
カキクケコ
サシスセソ
タチツテト
ナニヌネノ
ハヒフヘホ
マミムメモ
ヤユヨ
ラリルレロ
ワヲン
ァィゥェォ
ガギグゲゴ
ザジズゼゾ
ダヂヅデド
バビブベボ
パピプペポ"""
# 戻り値はジェネレータ型
gen = difflib.unified_diff(
# 文字列のリストやタプルの形で入力2つを指定
text1.splitlines(), text2.splitlines(),
# ファイル名部分2つを指定
"name-version.orig/test.txt", "name-version/test.txt",
# タイムスタンプ部分の文字列(1つ目のファイル)
# 今回は適当なタイムスタンプをフォーマット付けした
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(1145141919)),
# タイムスタンプ部分の文字列(2つ目のファイル)
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(1155680062)),
# 変更部分周辺をどの程度含めるか(既定値は3)
3,
# 制御行の末尾に付ける文字列
# CR+LFなdiffを書き出したいなら "\r" を記述する
"")
# for文でループさせる
for line in gen:
print(line)
if __name__ == "__main__":
main()
これを実行すると、下のようにそれぞれのテキスト部分を比較した結果がunified形式で表示される。これはdiff -u [ファイル1] [ファイル2]
のコマンド行を実行した結果とタイムスタンプ部分の表記の微妙な違いを除いて同一のものとなる。
--- name-version.orig/test.txt 2006-04-16 07:58:39
+++ name-version/test.txt 2006-08-16 07:14:22
@@ -5,10 +5,9 @@
なにぬねの
はひふへほ
まみむめも
-やゆよ
-らりるれろ
+やゆよら
+りるれろ
わをん
-がぎぐげご
ざじずぜぞ
だぢづでど
ばびぶべぼ
@@ -23,6 +22,7 @@
ヤユヨ
ラリルレロ
ワヲン
+ァィゥェォ
ガギグゲゴ
ザジズゼゾ
ダヂヅデド
3行目からの差分の部分については完全に同一だが、diff
コマンドでオプション指定により挙動を変えたり、difflib.unified_diff()
の7番目の引数を3
以外にしたりすると両者の出力は違ったものとなる。
関連記事
参考URL
使用したバージョン