Trình kiểm tra Diff văn bản

So sánh hai văn bản và tìm sự khác biệt ngay lập tức.

Dữ liệu của bạn không rời khỏi thiết bị

Về so sánh văn bản

Công cụ diff này sử dụng thuật toán dãy con chung dài nhất (LCS) để so sánh hai văn bản dòng theo dòng. Các bổ sung được làm nổi bật màu xanh lá và các xóa màu đỏ. Chọn chế độ xem «Inline» để xem tất cả các thay đổi trên một cột duy nhất, hoặc «Cạnh nhau» để so sánh các văn bản gốc và đã sửa đổi song song.

Các sử dụng phổ biến

Câu hỏi thường gặp

Nó có so sánh ký tự theo ký tự không?

Công cụ này so sánh dòng theo dòng. Nếu một dòng có một thay đổi nhỏ nhất (kể cả một ký tự duy nhất), toàn bộ dòng được đánh dấu là đã sửa đổi. Đây là cùng cách tiếp cận được sử dụng bởi Git và hầu hết các công cụ diff.

Có giới hạn kích thước không?

Không có giới hạn nghiêm ngặt, nhưng các văn bản rất lớn (hơn 10.000 dòng) có thể mất một chút thời gian để xử lý, vì so sánh chạy hoàn toàn trong trình duyệt của bạn.

Ý nghĩa thực sự của «diff»

Diff mô tả cách biến một văn bản thành văn bản khác bằng tập hợp chèn và xóa nhỏ nhất. Có vô số cách để làm điều đó, cách tầm thường là «xóa mọi ký tự của A rồi chèn mọi ký tự của B.» Một diff hữu ích là script chỉnh sửa ngắn nhất, là mặt đối ngẫu của bài toán Dãy Con Chung Dài Nhất: tìm dãy dài nhất các dòng xuất hiện (theo thứ tự) trong cả hai văn bản, và tất cả phần còn lại là thêm hoặc xóa. Hầu hết các thuật toán diff là các thuật toán LCS dưới một cái tên khác.

Một điểm tinh tế: dãy con chung dài nhất không phải là chuỗi con chung dài nhất. Dãy con bảo toàn thứ tự nhưng không cần liền kề, vì vậy «ABCDE» và «AXBYCZD» chia sẻ dãy con «ABCD» mặc dù không có chuỗi liên tiếp nào gồm ba ký tự xuất hiện trong cả hai.

Lịch sử ngắn gọn các thuật toán diff

Chương trình so sánh file được dùng rộng rãi đầu tiên là Unix diff được viết bởi Douglas McIlroy tại Bell Labs, với thuật toán cơ bản được công bố bởi James W. Hunt và McIlroy trong Báo cáo Kỹ thuật Khoa học Máy tính của Bell Labs #41 vào tháng 6 năm 1976. Bản thân McIlroy mô tả quá trình phát triển bốn tháng là «một nỗ lực tuyệt vọng.» Phương pháp Hunt-McIlroy băm mọi dòng của file B, lập chỉ mục nơi xuất hiện mỗi dòng duy nhất, và tìm kiếm chuỗi tăng đơn điệu dài nhất của các khớp. Nó được tích hợp trong Unix Version 6 và về cơ bản vẫn là cùng thuật toán trong /usr/bin/diff trên hầu hết các hệ thống Unix trong nhiều thập kỷ.

Eugene W. Myers công bố tiêu chuẩn công nghiệp hiện đại vào năm 1986, «An O(ND) Difference Algorithm and Its Variations» trong tạp chí Algorithmica Vol. 1, No. 2. Myers tái định nghĩa LCS thành bài toán đường đi ngắn nhất qua một đồ thị chỉnh sửa: đặt A dọc theo trục trên và B dọc theo trục bên, vẽ đường chéo bất cứ khi nào hai dòng khớp, và tìm kiếm đường đi từ trên-trái đến dưới-phải với ít cạnh không chéo nhất. Mỗi cạnh không chéo là một lần chèn hoặc xóa; mỗi đường chéo là miễn phí. Quan trọng hơn, thuật toán chạy trong thời gian O((N+M)·D) trong đó D là kích thước của script chỉnh sửa, tức là nó chạy nhanh hơn khi các file càng giống nhau. Đối với các diff kiểm soát phiên bản thông thường, D rất nhỏ so với N+M, vì vậy Myers nhanh hơn đáng kể so với trường hợp xấu nhất O(N·M) trong thực tế. Bài báo của ông cũng bao gồm cải tiến không gian tuyến tính sử dụng thủ thuật «middle snake» chia-để-trị. Thuật toán Myers là thuật toán mặc định cho GNU diff, git diff, Mercurial, Subversion, jsdiff, difflib của Python và hầu hết các trình xem diff GUI.

Bram Cohen (sau này nổi tiếng hơn với tư cách là người phát minh ra BitTorrent) đã thiết kế patience diff cho hệ thống kiểm soát phiên bản Bazaar vào khoảng năm 2002. Vấn đề thúc đẩy: Myers diff căn chỉnh bất kỳ dòng khớp nào, bao gồm cả những dòng rất phổ biến, vì vậy việc di chuyển một hàm trong C có thể tạo ra diff nhiễu trong đó dấu ngoặc đóng của hàm được di chuyển căn chỉnh với dấu ngoặc đóng của một hàm không liên quan. Patience diff neo diff trên các dòng xuất hiện đúng một lần trong mỗi file (thường là chữ ký hàm, tiêu đề chú thích, thông điệp log đặc trưng), tính LCS chỉ của các neo đó bằng patience sort, và đệ quy trên các khoảng trống. Kết quả căn chỉnh trên các dòng có ý nghĩa và dễ đọc hơn cho mã nguồn. Git hỗ trợ nó qua git diff --patience. Histogram diff là cải tiến được thêm vào git khoảng năm 2010 xây dựng histogram tần suất xuất hiện dòng và ưu tiên các neo tần suất thấp thay vì các neo hoàn toàn duy nhất; từ git 2.45 trở đi nó là mặc định cho nhiều cấu hình.

Levenshtein so với LCS

Một khái niệm liên quan đáng phân biệt. Khoảng cách Levenshtein (Vladimir Levenshtein, 1965) đếm số lần chèn, xóa và thay thế một ký tự tối thiểu để biến một chuỗi thành chuỗi khác. Diff dựa trên LCS có liên quan chặt chẽ nhưng hơi khác: diff cổ điển coi một «thay đổi» là một cặp xóa-rồi-chèn thay vì một lần thay thế đơn lẻ, vì điều đó phù hợp hơn với các file theo dòng. Levenshtein trả lời «những chuỗi này khác nhau như thế nào?» và cho bạn một con số; LCS trả lời «điều gì cụ thể đã thay đổi?» và cho bạn script chỉnh sửa thực tế. Bộ kiểm tra chính tả và các tính năng «bạn có muốn nói...?» muốn cái đầu; các công cụ diff muốn cái sau. Biến thể Damerau-Levenshtein (1964) mở rộng Levenshtein với toán tử hoán vị để phát hiện lỗi đánh máy.

Độ chi tiết: dòng, từ và ký tự

Diff có thể được tính ở các độ chi tiết khác nhau, mỗi loại có sự đánh đổi:

Một mẫu phổ biến trong các UI diff hiện đại là tính diff ở cấp dòng trước, sau đó đối với bất kỳ cặp «láng giềng đã xóa/thêm» nào, chạy diff cấp từ thứ cấp chỉ trên hai dòng đó và đánh dấu các thay đổi trong dòng. Đó chính xác là cách cả chế độ xem PR của GitHub và thư viện diff-match-patch hoạt động.

Ba chế độ hiển thị diff bạn sẽ thấy

Các biến thể git diff hữu ích

Khi nào bạn cần dùng browser diff

Giới hạn trung thực

Thêm câu hỏi

Tại sao trang này không hiển thị đánh dấu cấp ký tự bên trong các dòng đã thay đổi?

Vì lần diff cấp dòng là đủ cho hầu hết các trường hợp sử dụng và chạy nhanh hơn nhiều trên đầu vào dài. Đối với đánh dấu từng từ trong dòng, cải tiến hai bước là thực hành tiêu chuẩn nhưng thêm độ trễ. Nếu sự khác biệt toàn bộ dòng quan trọng với bạn (đánh dấu pháp lý, đọc thử văn xuôi), một công cụ cấp từ chuyên dụng (bao gồm git diff --word-diff trên dòng lệnh) phù hợp hơn.

Sự khác biệt giữa unified diff và side-by-side là gì?

Unified diff là định dạng gọn gàng, đọc được bởi máy mà mọi file .patch sử dụng, ba dòng ngữ cảnh, các hunk được đánh dấu bằng @@. Side-by-side hiển thị hai phiên bản trong các cột song song, dễ nhìn hơn để xem xét trực quan nhưng chiếm nhiều không gian ngang hơn. Unified là thứ bạn sẽ email hoặc commit; side-by-side là thứ bạn sẽ đọc trên màn hình rộng.

Có thuật toán nào tốt hơn Myers cho mã nguồn không?

Đối với mã nguồn có các hàm được di chuyển hoặc sắp xếp lại lớn, có, patience diff (Bram Cohen, 2002) và histogram diff (git, khoảng năm 2010) được thiết kế để căn chỉnh trên các dòng duy nhất có ý nghĩa thay vì các dòng phổ biến, tạo ra đầu ra dễ đọc hơn. Cả hai đều có thể dùng qua git diff --patiencegit diff --histogram. Các công cụ hiểu AST như difftastic đi xa hơn và phân tích cấu trúc ngôn ngữ thực tế.

Có an toàn để dán văn bản bí mật ở đây không?

Có, diff chạy hoàn toàn trong trình duyệt của bạn bằng cách sử dụng triển khai LCS JavaScript. Không có gì được tải lên, không có phân tích trên đầu vào, không có nhật ký phía máy chủ về văn bản. Đây là danh mục công cụ diff duy nhất an toàn cho NDA, mã nguồn nội bộ, hoặc các điều khoản hợp đồng chưa phát hành; các dịch vụ diff trên đám mây thấy bất cứ thứ gì bạn dán vào.

Công cụ liên quan