เปรียบเทียบไฟล์ซอร์สโค้ดโดยไม่สนใจความแตกต่างของการจัดรูปแบบ (เช่นช่องว่าง, การแบ่งบรรทัด, ... )


9

ฉันกำลังมองหาแอปพลิเคชันที่สามารถเปรียบเทียบสองแหล่ง C ++ และค้นหาความแตกต่างที่มีความหมายรหัส (เพื่อเปรียบเทียบรุ่นที่อาจมีการจัดรูปแบบแตกต่างกัน) อย่างน้อยที่สุดสิ่งที่มีความสามารถในการเพิกเฉยต่อการเปลี่ยนแปลงในพื้นที่สีขาวพื้นที่แท็บและการขึ้นบรรทัดใหม่ซึ่งไม่ส่งผลกระทบต่อการทำงานของแหล่งที่มา (โปรดทราบว่าการขึ้นบรรทัดใหม่นั้นถือเป็นช่องว่างขึ้นอยู่กับภาษาและ C และ C ++ ) และสิ่งที่สามารถระบุความแตกต่างที่มีความหมายรหัสทั้งหมด ฉันอยู่ภายใต้ Ubuntu

ตามที่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 - โปรแกรม diff คำที่มีการคั่น

โปรแกรมฉลาดมาก - ดู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

ฉันสงสัยว่านี่เป็นสิ่งที่แตกต่างกัน หากมีการเปลี่ยนแปลงพื้นที่ภายในหนึ่งบรรทัดมันจะทำงาน (หรือโปรแกรมอื่นที่คล้ายคลึงกันเช่น kompare) ที่แย่กว่านั้นคุณสามารถทำการค้นหาและแทนที่และยุบตัวอักษรของแท็บ ฯลฯ แต่สิ่งที่คุณต้องการสำหรับการเปลี่ยนแปลงช่องว่างนอกบรรทัด ...

คุณต้องมีโปรแกรมที่เข้าใจภาษา C ++ โปรดทราบว่าทุกภาษามีความแตกต่างและโดยเฉพาะอย่างยิ่ง Python ใช้ช่องว่างเพื่อกำหนดบล็อคโค้ด ด้วยเหตุนี้ฉันจึงสงสัยว่าโปรแกรมที่คล้ายกันทั่วไปจะทำงานกับภาษาการเขียนโปรแกรม "any" (หรือเฉพาะ)

คุณอาจพิจารณาตัวแยกวิเคราะห์บางชนิดเพื่อดูไฟล์ต้นฉบับสองไฟล์จากนั้นเปรียบเทียบผลลัพธ์ของตัวแยกวิเคราะห์นี้

นี้อยู่นอกเหนือพื้นหลังของฉัน แต่ฉันขอแนะนำให้คุณมองเข้าไปในไฟแนนเชี่และYacc นี่คือหน้า Wikipedia; คุณอาจต้องการดูหน้านี้ซึ่งให้คำอธิบายที่กระชับและตัวอย่าง


ฉันไม่คิดว่าฉันต้องการบางอย่างที่เข้าใจ C ++ เป็นพิเศษ (อย่างน้อยสำหรับการละเว้นความแตกต่างเนื่องจากการขึ้นบรรทัดใหม่) ฉันไม่จำเป็นต้องรวบรวมแหล่งที่มา มันจะต้องแตกต่างกันอย่างเหมาะสมโดยไม่คำนึงถึงภาษา จริงๆแล้วมีคำตอบอื่นที่แนะนำ dwdiff ยังคงต้องทดสอบ แต่ตัวอย่างที่ให้มาดูน่าเชื่อถือ
sancho.s ReinstateMonicaCellio

Lex / Yacc ไม่ได้รวบรวมซอร์สโค้ดตามลำดับ มันจะแยกเป็นโทเค็น ตัวอย่างเช่นหากคุณมี "int foo = 0" vs "int bar = 0" จะเห็นได้ชัดว่า foo และ bar เป็นคำที่ต่างกันสองคำ แต่ในบริบทของโปรแกรมพวกเขาเหมือนกันจริงๆ หากคุณต้องการจับความคล้ายคลึงกันเช่นนี้คุณอาจต้องใช้โปรแกรมแยกวิเคราะห์ ถ้าคุณทำไม่ได้แน่นอนคำแนะนำ dwdiff ดูเหมือนจะดีมาก โชคดี!
เรย์

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( uncrustify's mod_full_brace_ifอาจจะถูกใช้ในการบังคับใช้การแทรก / กำจัดของวงเล็บปีกการอบบรรทัดเดียวifของร่างกาย)

นอกจากนี้หากparallelไม่ได้ติดตั้งGNU ให้ใช้xargs- มันทำเหมือนกัน แต่จะนานกว่าเล็กน้อย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.