형식 차이를 무시하고 소스 코드 파일 비교 (공백, 줄 바꿈 등)


9

두 개의 C ++ 소스를 비교하고 코드 의미가 다른 차이점을 찾을 수있는 응용 프로그램을 찾고 있습니다 (서로 다시 포맷 된 버전을 비교하기 위해). 최소한 공백, 탭 공백 및 줄 바꿈의 변경을 무시할 수있는 기능은 소스의 기능에 영향을 미치지 않는 것입니다 (줄 바꿈이 공백 으로 간주되는지 여부는 C 및 C ++은 그렇지 않습니다) ). 이상적으로는 코드를 의미하는 모든 차이점을 정확히 식별 할 수있는 것이 이상적입니다. 우분투에 있습니다.

에 따르면 diff --help | grep ignore, 나는 합리적 으로 일 diff -bBwZ을 할 것으로 예상 했다 (나중에 처리 할 거짓 부정을 기대했다). 그럼에도 불구하고 그렇지 않습니다.

스 니펫이있는 다음 파일이있는 경우

test_diff1.txt

    else if (prop == "P1") { return 0; }

및 test_diff2.txt

    else if (prop == "P1") {
        return 0;
    }

그때

$ diff -bBwZ test_diff1.txt test_diff2.txt
1c1,3
<     else if (prop == "P1") { return 0; }
---
>     else if (prop == "P1") {
>         return 0;
>     }

빈 결과 대신.

두 입력에서 코드 포맷터를 "필터"로 사용하면 이러한 차이를 걸러 낼 수 있지만 실제 텍스트와 줄 번호를 유지하려면 차이를 최종보고하기 위해 결과 출력을 원래 입력에 다시 연결해야합니다. 따라서 컴파일러가 필요하지 않고 목표를 달성 할 수 있습니다 ...하지만 무언가가 사용 가능한지 모르겠습니다.

목표를 달성 할 수 있습니까 diff? 그렇지 않으면 대안이 있습니까? (바람직하게는 명령 행)?

답변:


6

사용할 수 있습니다 dwdiff. 보낸 사람 man dwdiff:

dwdiff -구분 된 단어 차이 프로그램

프로그램은 매우 영리합니다-참조 dwdiff --help:

$ dwdiff --help
Usage: dwdiff [OPTIONS] <OLD FILE> <NEW FILE>
-h, --help                             Print this help message
-v, --version                          Print version and copyright information
-d <delim>, --delimiters=<delim>       Specify delimiters
-P, --punctuation                      Use punctuation characters as delimiters
-W <ws>, --white-space=<ws>            Specify whitespace characters
-u, --diff-input                       Read the input as the output from diff
-S[<marker>], --paragraph-separator[=<marker>]  Show inserted or deleted blocks
                               of empty lines, optionally overriding the marker
-1, --no-deleted                       Do not print deleted words
-2, --no-inserted                      Do not print inserted words
-3, --no-common                        Do not print common words
-L[<width>], --line-numbers[<width>]   Prepend line numbers
-C<num>, --context=<num>               Show <num> lines of context
-s, --statistics                       Print statistics when done
--wdiff-output                         Produce wdiff compatible output
-i, --ignore-case                      Ignore differences in case
-I, --ignore-formatting                Ignore formatting differences
-m <num>, --match-context=<num>        Use <num> words of context for matching
--aggregate-changes                    Allow close changes to aggregate
-A <alg>, --algorithm=<alg>            Choose algorithm: best, normal, fast
-c[<spec>], --color[=<spec>]           Color mode
-l, --less-mode                        As -p but also overstrike whitespace
-p, --printer                          Use overstriking and bold text
-w <string>, --start-delete=<string>   String to mark begin of deleted text
-x <string>, --stop-delete=<string>    String to mark end of deleted text
-y <string>, --start-insert=<string>   String to mark begin of inserted text
-z <string>, --stop-insert=<string>    String to mark end of inserted text
-R, --repeat-markers                   Repeat markers at newlines
--profile=<name>                       Use profile <name>
--no-profile                           Disable profile reading

다음과 같이 테스트하십시오.

cat << EOF > test_diff1.txt
    else if (prop == "P1") { return 0; }
EOF

cat << EOF > test_diff2.txt
    else if (prop == "P1") {
        return 0;
    }
EOF

그런 다음 비교를 시작하십시오.

$ dwdiff test_diff1.txt test_diff2.txt --statistics
    else if (prop == "P1") {
        return 0;
    }
old: 9 words  9 100% common  0 0% deleted  0 0% changed
new: 9 words  9 100% common  0 0% inserted  0 0% changed

100% common상기 사항에 유의하십시오 .


1

나는 이것이 diff가 할 수있는 일인지 의심합니다. 줄에 공간이 변경되면 작동합니다 (또는 kompare와 같은 다른 유사한 프로그램). 더 나쁜 것은 검색 및 바꾸기 및 축소 탭 문자 등을 수행 할 수 있다는 것입니다. 그러나 공백을 요구하는 것은 한 줄 이상으로 변경됩니다 ...

C ++ 언어를 이해하는 프로그램이 필요합니다. 모든 언어가 다르고 특히 Python은 공백을 사용하여 코드 블록을 정의합니다. 따라서, 일반적인 diff-like 프로그램이 "모든"(또는 특정) 프로그래밍 언어와 함께 작동하지 않을 것입니다.

어떤 종류의 구문 분석기가 두 개의 소스 파일을 통과 한 다음이 구문 분석기의 출력을 비교하는 것을 고려할 수 있습니다.

이것은 내 배경을 넘어서지 만 LexYacc 를 살펴 보는 것이 좋습니다 . 이들은 Wikipedia 페이지입니다. 간결한 설명과 예를 제공하는 페이지를 살펴볼 수 있습니다 .


나는 적어도 C ++을 이해하는 무언가가 필요하지 않다고 생각합니다 (적어도 개행으로 인한 차이점을 무시하기 위해), 소스를 컴파일 할 필요가 없습니다. 언어에 관계없이 적절하게 차이를 내면됩니다. 실제로 dwdiff를 제안하는 또 다른 대답이 있습니다. 여전히 테스트해야하지만 제공된 예제는 설득력이 있습니다.
sancho.s ReinstateMonicaCellio

Lex / Yacc는 소스 코드 자체를 컴파일하지 않습니다. 토큰으로 분리합니다. 예를 들어, "int foo = 0"대 "int bar = 0"이 있다면 분명히 foo와 bar는 서로 다른 단어입니다. 그러나 프로그램의 맥락에서 그들은 실제로 동일합니다. 이와 같은 유사점을 찾으려면 일종의 파서가 필요할 수 있습니다. 그렇지 않으면 dwdiff 제안이 아주 좋은 것 같습니다. 행운을 빕니다!
Ray

0

비슷한 상황 git에서 코드 형식화에 관계없이 두 가지 를 비교해야 할 때 다음과 같이했습니다.

  1. 임시 지점을 만들었습니다.

    $ git co feature-a
    $ git co -b 1
    $ git co feature-b
    $ git co -b 2
    
  2. 다음을 사용하여 두 가지를 모두 포맷했습니다 clang-format.

    $ git co 1
    $ find . -name '*.cpp' -print0 | parallel -0 -n 1 clang-format -i -style=google
    $ git ci -a -m1 --no-verify
    $ git co 2
    $ find . -name '*.cpp' -print0 | parallel -0 -n 1 clang-format -i -style=google
    $ git ci -a -m2 --no-verify
    
  3. 실제 비교를했다 :

    $ git diff -w -b 1 2
    

    ( -w -b경우에 따라 공간 차이를 무시할 수 있습니다).

uncrustify이상을 선호 할 수 있습니다 clang-format( uncrustifymod_full_brace_if단일 라인 if본문에 중괄호를 삽입 / 제거하는 데 사용될 수 있음 ).

또한 GNU parallel가 설치되어 있지 않은 경우 사용 xargs하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.