2021년 11월 12일 금요일

Python 문장(문자열)의 비교, diff 생성,patch 생성, beyond compare 처럼 구현하기(실전 예제)

앞에서 간단하게 SequenceMatcher의 함수에 대해서 살펴 보았습니다.

https://swlock.blogspot.com/2021/11/python-diff-patch-beyond-compare.html

이번에는 좀 더 실전적인 예제를 통해서 쓸만한 함수를 살펴 보도록 하겠습니다.

어떤 주어진 데이터의 비교 결과를 colorful 하게 표시하는게 이번 시간의 목표입니다. 칼라로 표시하려면 여러가지 방식이 있겠지만 가장 간단한 방법은 html tag로 표시해서 브라우저로 보는 방법입니다.


목표

브라우저로 결과물을 열었을때 다음과 같이 다른 부분만 색상이 다르게 나오도록 작업합니다.




전체 코드

from difflib import SequenceMatcher

def get_diff_colored(string1,string2,diff_color):
	reta = ""
	retb = ""
	
	s = SequenceMatcher(None,string1,string2)
	
	for tag,i1,i2,j1,j2 in s.get_opcodes():
		if tag=='equal':
			reta += string1[i1:i2]
			retb += string2[j1:j2]
		else:
			reta += '<span style="color:rgb('+diff_color+');">'+string1[i1:i2]+'</span>'
			retb += '<span style="color:rgb('+diff_color+');">'+string2[j1:j2]+'</span>'
			
	return [reta,retb]

def change_dspace_to_space(string_data):
	while True:
		slen = len(string_data)
		string_data = string_data.replace("  "," ")
		if len(string_data)==slen:
			return string_data

if __name__ == '__main__':
	ret = get_diff_colored("    Hallo   God    Monin  123,  12312, 123,   123,  12312","Hello Good Morning 123 12312,123,123,2312","255,0,0")
	print("<html><body>")
	print(ret[0])
	print("<BR>")
	print(ret[1])
	ret = get_diff_colored(change_dspace_to_space("    Hallo   God    Monin  123,  12312, 123,   123,  12312"),change_dspace_to_space("Hello Good Morning 123 12312,123,123,2312"),"255,0,0")
	print("<BR>")
	print("<BR>")
	print(ret[0])
	print("<BR>")
	print(ret[1])
	print("</body></html>")

실제 화면 출력

python sequencemacher_test.py 실행시키면 아래와 같은 형태로 나옵니다.

<html><body>
<span style="color:rgb(255,0,0);">    </span>H<span style="color:rgb(255,0,0);">a</span>llo <span style="color:rgb(255,0,0);">  </span>G<span style="color:rgb(255,0,0);"></span>od <span style="color:rgb(255,0,0);">   </span>Mo<span style="color:rgb(255,0,0);"></span>nin<span style="color:rgb(255,0,0);"> </span> 123<span style="color:rgb(255,0,0);">, </span> 12312,<span style="color:rgb(255,0,0);"> </span>123,<span style="color:rgb(255,0,0);">   </span>123,<span style="color:rgb(255,0,0);">  1</span>2312
<BR>
<span style="color:rgb(255,0,0);"></span>H<span style="color:rgb(255,0,0);">e</span>llo <span style="color:rgb(255,0,0);"></span>G<span style="color:rgb(255,0,0);">o</span>od <span style="color:rgb(255,0,0);"></span>Mo<span style="color:rgb(255,0,0);">r</span>nin<span style="color:rgb(255,0,0);">g</span> 123<span style="color:rgb(255,0,0);"></span> 12312,<span style="color:rgb(255,0,0);"></span>123,<span style="color:rgb(255,0,0);"></span>123,<span style="color:rgb(255,0,0);"></span>2312
<BR>
<BR>
<span style="color:rgb(255,0,0);"> </span>H<span style="color:rgb(255,0,0);">a</span>llo Go<span style="color:rgb(255,0,0);"></span>d Mo<span style="color:rgb(255,0,0);"></span>nin<span style="color:rgb(255,0,0);"></span> 123<span style="color:rgb(255,0,0);">,</span> 12312,<span style="color:rgb(255,0,0);"> </span>123,<span style="color:rgb(255,0,0);"> </span>123,<span style="color:rgb(255,0,0);"> 1</span>2312
<BR>
<span style="color:rgb(255,0,0);"></span>H<span style="color:rgb(255,0,0);">e</span>llo Go<span style="color:rgb(255,0,0);">o</span>d Mo<span style="color:rgb(255,0,0);">r</span>nin<span style="color:rgb(255,0,0);">g</span> 123<span style="color:rgb(255,0,0);"></span> 12312,<span style="color:rgb(255,0,0);"></span>123,<span style="color:rgb(255,0,0);"></span>123,<span style="color:rgb(255,0,0);"></span>2312
</body></html>

위와 같은 콘솔 출력 상태는 브라우저에서 볼 수가 없으므로 파일로 저장이 필요합니다.

그럼 결과를 파일로 저장하는 ">" 리다이렉션을 사용합니다.

python sequencemacher_test.py > 1.html

1.html 을 브라우저로 열도록 합니다.


코드 설명

SequenceMatcher 의 get_opcodes 함수를 사용하였습니다. 이 함수는 다른부분 삭제된 부분 그런 자세한 위치를 알려주는 함수인데 같은 부분만 사용하고 나머지는 다르다고 판단하고 색상을 넣었습니다. 색상을 넣을때는 html span style tag를 사용하였습니다.

그리고 간혹 white space처리가 제대로 안되는 경우가 있었습니다. white space가 여러개 있는 경우 하나로 변경하는 처리를 따로 구현하였습니다. change_dspace_to_space 함수



댓글 없음:

댓글 쓰기