2021년 11월 7일 일요일

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


문자열 비교 함수는 많이 들어봤을 것입니다. 

python에서는 조건식을 이용하면 일치하는지 쉽게 알 수 있습니다. 아니면 한글자씩 비교하는것도 가능할겁니다.

그런데, 여기에서 구현하고자하는 것은 다른 부분은 색상이 들어오게 하는것입니다. 즉 patch 스타일과 비슷합니다. 물론 최종 목표는 patch형태는 아니지만 전체적인 내용을 확인하는데 도움이 되기 위해서는 patch를 이해하는것이 중요합니다.

patch가 어떤것이냐면,,,, 아래와 같은 형태를 말하는것 입니다. 

git diff로 생성시키면 나오는 patch 파일입니다.

--- a/src/main/java/hello/HelloWorld.java
+++ b/src/main/java/hello/HelloWorld.java
@@ -4,6 +4,7 @@ public class HelloWorld {
     public static void main(String[] args) {
-        String suffix = "@@@";
-        System.out.println(suffix);
+ String prefix = "$$$" + System.out.println(prefix);
} }

이것을 아무런 지식없이 구현하려면 아무래도 신경을 써야 할텐데... python은 기본으로  library에 기능이 있습니다.

여기에서는 단순히 라인에 대해서만 나오고 있지만 실제는 text 문장끼리도 차이점을 알아내도록 준비가 되어있습니다.


difflib 라는 패키지를 소개합니다.

https://docs.python.org/ko/3/library/difflib.html

여기에서는 공식 문서에 기본적인 예제의 내용을 보다 쉽게 설명하고, 다음에 기회가 되면 좀더 실전 예제를 만들어서 소개하도록 하겠습니다.


아래 함수 두개가 patch형태를 만들어 내는 함수입니다.

class difflib.Differ

class difflib.HtmlDiff

사실 이글을 시작하게 되면서 patch를 원했던것은 아니라서 이 부분의 예제의 설명은 건너 뛰도록 하겠습니다.

원하는것은 SequenceMatcher 입니다. 이것은 두개의 문장이나 혹은 두개의 문자열에서 일치하는 부분을 알려주는 class 입니다.

예제:

from difflib import SequenceMatcher

str1="abcde"
str2=" abce"
s = SequenceMatcher(None, str1, str2)
print(s.get_matching_blocks())
for mb in s.get_matching_blocks():
	print(mb, str1[mb.a:mb.a+mb.size])
	print(mb, str2[mb.b:mb.b+mb.size])

첫번째인자는 junk 조건을 넣는데, 기본으로 None 입력 해주면 됩니다.

예제로 주어진 문장은 공백도 있어서 단순히 첫번째 글자와 비교를 하면 처리가 복잡해집니다만, 결과를 보면 아주 만족스럽게 처리를 하고 있습니다. macher 결과는 a , b 두개의 위치 정보가 주어지는데 결국은 아래에서 보듯이 같게 됩니다. ( 일치하는 정보이기 때문 )

결과:

[Match(a=0, b=1, size=3), Match(a=4, b=4, size=1), Match(a=5, b=5, size=0)]
Match(a=0, b=1, size=3) abc
Match(a=0, b=1, size=3) abc
Match(a=4, b=4, size=1) e
Match(a=4, b=4, size=1) e
Match(a=5, b=5, size=0)
Match(a=5, b=5, size=0)


실전 예제

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

댓글 없음:

댓글 쓰기