Làm thế nào tôi có thể nhận diff để chỉ hiển thị các dòng được thêm và xóa? Nếu diff không thể làm điều đó, công cụ nào có thể?


69

Làm thế nào tôi có thể nhận diff để chỉ hiển thị các dòng được thêm và xóa? Nếu diff không thể làm điều đó, công cụ nào có thể?


2
Bạn cần xác định rõ hơn những gì bạn muốn nói bằng cách thêm và xóa. Cụ thể, một dòng có thể thay đổi? Nếu vậy, làm thế nào để bạn muốn một dòng thay đổi được xử lý? Nếu bạn đang thực hiện kiểm tra theo định hướng nghiêm ngặt, việc thay đổi dòng giống hệt với dòng cũ bị xóa và dòng mới được thêm vào. Ví dụ, làm thế nào để xử lý một dòng chia làm hai? Khi hai dòng 1 thay đổi? 2 dòng thay đổi? Xóa 1 dòng và thêm 2 dòng? Trừ khi bạn có thể đảm bảo rằng các dòng sẽ không bao giờ thay đổi, chỉ cần được thêm và xóa, tôi nghĩ điều này sẽ thất bại nếu không có định nghĩa tốt hơn.
Christopher Cashell

Tôi thấy câu hỏi khá không rõ ràng. Nhưng ít nhất một cách giải thích câu hỏi có thể được trả lời bằngdiff A B | grep '^[<>]'
kasperd

Bạn có thể đang tìm kiếm comm.
Jenny D

@ChristopherCashell, Ông có nghĩa là bỏ qua thứ tự sắp xếp; một vấn đề thường gặp Thông thường, điều này được thực hiện bằng cách sắp xếp đầu tiên các phân đoạn (dòng) ở mỗi bên trước khi thực hiện một khác biệt điển hình.
Pacerier

@Pacerier, bạn có chắc về điều đó? Hay bạn đang đoán? Không có gì về sắp xếp hoặc thứ tự tìm kiếm được đề cập hoặc gợi ý trong câu hỏi. Khi nó đứng, câu hỏi không rõ ràng và có thể được giải thích theo nhiều cách khác nhau. Không biết chắc chắn những gì anh ấy đang hỏi, chúng tôi đang đưa ra các giả định và đưa ra các giải pháp có thể hoặc không thể giải quyết vấn đề thực tế. Ngoài ra, nhận xét của người đăng ban đầu về một trong những câu trả lời cho thấy điều này không liên quan đến việc sắp xếp. Nó không liên quan đến ý nghĩa của "thêm và xóa" so với "đã thay đổi".
Christopher Cashell

Câu trả lời:


82

Hãy thử

Một cách khác để xem xét nó:

  • Hiển thị các dòng chỉ tồn tại trong tệp a: (tức là những gì đã bị xóa khỏi a)

    comm -23 a b
    
  • Hiển thị các dòng chỉ tồn tại trong tệp b: (tức là những gì đã được thêm vào b)

    comm -13 a b
    
  • Hiển thị các dòng chỉ tồn tại trong một tệp này hoặc tệp khác: (nhưng không phải cả hai)

    comm -3 a b | sed 's/^\t//'
    

(Cảnh báo: Nếu tệp acó các dòng bắt đầu bằng TAB, thì nó (TAB đầu tiên) sẽ bị xóa khỏi đầu ra.)

Chỉ sắp xếp các tệp

LƯU Ý: Cả hai tệp cần được sắp xếp commđể hoạt động chính xác. Nếu chúng chưa được sắp xếp, bạn nên sắp xếp chúng:

sort <a >a.sorted
sort <b >b.sorted
comm -12 a.sorted b.sorted

Nếu các tệp quá dài, đây có thể là một gánh nặng khá lớn vì nó yêu cầu một bản sao thêm và do đó gấp đôi dung lượng đĩa.


5
chỉ muốn thêm rằng cả hai tệp cần được sắp xếp (phân biệt chữ hoa chữ thường) cho giải pháp này để tạo ra kết quả chính xác
marmor

1
Trên các vỏ đủ hiện đại, bạn có thể sắp xếp phù hợp với thứ gì đó nhưcomm -12 <(sort a) <(sort b)
Joshua Huber

14

commcó thể làm những gì bạn muốn. Từ trang người đàn ông của nó:

SỰ MIÊU TẢ

So sánh các tệp được sắp xếp FILE1 và FILE2 theo từng dòng.

Không có tùy chọn, sản xuất đầu ra ba cột. Cột một chứa các dòng duy nhất cho FILE1, cột hai chứa các dòng duy nhất cho FILE2 và cột ba chứa các dòng chung cho cả hai tệp.

Các cột này có thể được nén với -1, -2-3tương ứng.

Thí dụ:

[root@dev ~]# cat a
common
shared
unique

[root@dev ~]# cat b
common
individual
shared

[root@dev ~]# comm -3 a b
    individual
unique

Và nếu bạn chỉ muốn các dòng duy nhất và không quan tâm đến tập tin nào trong đó:

[root@dev ~]# comm -3 a b | sed 's/^\t//'
individual
unique

Như trang man nói, các tập tin phải được sắp xếp trước.


9

Để hiển thị các bổ sung và xóa mà không có ngữ cảnh, số dòng, +, -, <,>! vv, bạn có thể sử dụng diff như thế này:

diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt 

Ví dụ: đưa ra hai tệp:

a.txt

Common
Common
A-ONLY
Common

b.txt

Common
B-ONLY
Common
Common

Lệnh sau sẽ hiển thị các dòng hoặc bị xóa khỏi a hoặc được thêm vào b:

diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt 

đầu ra:

B-ONLY
A-ONLY

Lệnh hơi khác này sẽ hiển thị các dòng bị xóa khỏi a.txt:

diff --changed-group-format='%<' --unchanged-group-format='' a.txt b.txt 

đầu ra:

A-ONLY

Cuối cùng, lệnh này sẽ hiển thị các dòng được thêm vào a.txt

diff --changed-group-format='%>' --unchanged-group-format='' a.txt b.txt 

đầu ra

B-ONLY

2

Đó là những gì diff làm theo mặc định ... Có lẽ bạn cần thêm một số cờ để bỏ qua khoảng trắng?

diff -b -B

nên bỏ qua các dòng trống và số lượng không gian khác nhau.


1
Không, nó cũng hiển thị các dòng THAY ĐỔI (các dòng có một ký tự hoặc bốn khác nhau). Tôi muốn các dòng chỉ tồn tại ở bên trái hoặc bên phải.
C. Ross

2
Bạn có thể lập luận rằng các phiên bản khác nhau của tệp THAY ĐỔI chỉ tồn tại ở bên trái hoặc bên phải.
markdrayton

2
Không có cách nào để diff (hoặc bất kỳ công cụ nào khác) có thể nói một cách đáng tin cậy về sự thay đổi và dòng nào bị xóa được thay thế bằng một dòng mới.
Cian

1
Về mặt kỹ thuật, diff xử lý một dòng "đã thay đổi" như thể dòng gốc đã bị xóa và một dòng mới được thêm vào ... vì vậy về mặt kỹ thuật, nó hiển thị cho bạn chỉ các dòng được thêm và xóa.
KFro

2

Không, diffkhông thực sự cho thấy sự khác biệt giữa hai tệp theo cách người ta có thể nghĩ. Nó tạo ra một chuỗi các lệnh chỉnh sửa cho một công cụ muốn patchsử dụng để thay đổi một tệp thành một tệp khác.

Khó khăn cho bất kỳ nỗ lực nào trong việc thực hiện những gì bạn đang tìm kiếm là làm thế nào để xác định những gì tạo thành một dòng đã thay đổi so với một dòng bị xóa theo sau là một dòng được thêm vào. Ngoài ra, phải làm gì khi các dòng được thêm, xóa và thay đổi liền kề nhau.


Suy nghĩ của tôi chính xác. Bao nhiêu phần trăm ký tự trong một dòng phải thay đổi để coi nó là một cái mới thay vì sửa đổi bản gốc? Về mặt kỹ thuật ngay cả khi bạn có một ký tự chung, bạn có thể coi đó là "thay đổi" thay vì xóa và chèn.
Kamil Kisiel

1
Đã lâu rồi tôi mới xem các diffnguồn, nhưng dường như tôi nhớ tất cả các cách điều hướng để theo dõi nơi hai tập tin khớp nhau và tôi nghĩ có một ngưỡng từ bỏ dựa trên khoảng cách xa nhau dòng là. Nhưng tôi không nhớ bất kỳ kết hợp nội dòng nào ngoại trừ (tùy chọn) thu gọn khoảng trắng hoặc bỏ qua trường hợp. Hoặc (có lẽ) từ để ảnh hưởng. Trong mọi trường hợp, đó là tất cả về patchvà "vgrep" chỉ đi cùng cho chuyến đi. Có lẽ. Vào thứ ba.
Dennis Williamson

2

Các công cụ so sánh trực quan khớp hai tệp với nhau để một phân đoạn có cùng số dòng nhưng nội dung khác nhau sẽ được coi là một phân đoạn đã thay đổi. Các dòng hoàn toàn mới giữa các phân đoạn khớp được coi là các phân đoạn được thêm vào.

Đây cũng là cách công cụ dòng lệnh sdiff hoạt động, cho thấy sự so sánh song song của hai tệp trong một thiết bị đầu cuối. Các dòng thay đổi được phân tách bằng | tính cách. Nếu một dòng chỉ tồn tại trong tệp A, <được sử dụng làm ký tự phân cách. Nếu một dòng chỉ tồn tại trong tệp B,> được sử dụng làm dấu phân cách. Nếu bạn không có <và> ký tự trong tệp, bạn có thể sử dụng ký tự này để chỉ hiển thị các dòng đã thêm:

sdiff A B | grep '[<>]'

2

Cảm ơn senarvi, giải pháp của bạn (không được bình chọn) thực sự đã cho tôi CHÍNH XÁC những gì tôi muốn sau khi tìm kiếm độ tuổi trên một tấn trang.

Sử dụng câu trả lời của bạn, đây là những gì tôi nghĩ ra để có được danh sách những thứ đã thay đổi / thêm / xóa. Ví dụ này sử dụng 2 phiên bản của tệp / etc / passwd và in tên người dùng cho các bản ghi liên quan.

#!/bin/bash
sdiff passwd1 passwd2 | grep '[|]' | awk -F: '{print "changed: " $1}'
sdiff passwd1 passwd2 | grep '[<]' | awk -F: '{print "deleted: " $1}'
sdiff passwd1 passwd2 | grep '[>]' | awk -F\> '{print $2}' | awk -F: '{print "added: " $1}'

Lưu ý rằng vì sự khác biệt giữa "một dòng đã được sửa đổi" và "một dòng đã bị xóa và một dòng khác đã được thêm vào bên dưới hoặc bên trên nó" là ngữ nghĩa. Một công cụ tìm khác biệt dựa trên văn bản không thể tách rời những trường hợp. Do đó, câu trả lời dựa trên sdiff của bạn không thể hoạt động đáng tin cậy cho tất cả các trường hợp.
Mikko Rantalainen

0

Tôi thấy hình thức đặc biệt này thường hữu ích:

diff --changed-group-format='-%<+%>' --unchanged-group-format='' f g

Thí dụ:

printf 'a\nb\nc\nd\ne\nf\ng\n' > f
printf 'a\nB\nC\nd\nE\nF\ng\n' > g
diff --old-line-format=$'-%l\n' \
     --new-line-format=$'+%l\n' \
     --unchanged-line-format='' \
     f g

Đầu ra:

-b
-c
+B
+C
-e
-f
+E
+F

Vì vậy, nó hiển thị các dòng cũ với -ngay sau đó là dòng mới tương ứng với +.

Nếu chúng tôi đã xóa C:

printf 'a\nb\nd\ne\nf\ng\n' > f
printf 'a\nB\nC\nd\nE\nF\ng\n' > g
diff --old-line-format=$'-%l\n' \
     --new-line-format=$'+%l\n' \
     --unchanged-line-format='' \
     f g

nó trông như thế này:

-b
+B
+C
-e
-f
+E
+F

Các định dạng được ghi lại tại man diff:

       --line-format=LFMT
              format all input lines with LFMT`

và:

       LTYPE is 'old', 'new', or 'unchanged'.
              GTYPE is LTYPE or 'changed'.

và:

              LFMT (only) may contain:

       %L     contents of line

       %l     contents of line, excluding any trailing newline

       [...]

Câu hỏi liên quan: https://stackoverflow.com/questions/15384818/how-to-get-the-difference-only-additions-b between-two-files-in-linux

Đã thử nghiệm trong Ubuntu 18.04.


-1

Tệp1:

text670_1
text067_1
text067_2

Tệp2:

text04_1
text04_2
text05_1
text05_2
text067_1
text067_2
text1000_1

Sử dụng:

diff -y file1 file2

Điều này hiển thị hai cột cho các tập tin repectives.

Đầu ra:

text670_1                           
                                  > text04_1
                                  > text04_2
                                  > text05_1
                                  > text05_2
text067_1                           text67_1
text067_2                           text67_2
                                  > text1000_1
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.