Tôi muốn so sánh tệp1 với tệp2 và tạo tệp 3 chứa các dòng trong tệp1 không có trong tệp2.
Tôi muốn so sánh tệp1 với tệp2 và tạo tệp 3 chứa các dòng trong tệp1 không có trong tệp2.
Câu trả lời:
diff (1) không phải là câu trả lời, nhưng comm (1) là.
NAME
comm - compare two sorted files line by line
SYNOPSIS
comm [OPTION]... FILE1 FILE2
...
-1 suppress lines unique to FILE1
-2 suppress lines unique to FILE2
-3 suppress lines that appear in both files
Vì thế
comm -2 -3 file1 file2 > file3
Các tệp đầu vào phải được sắp xếp. Nếu không, hãy sắp xếp chúng trước. Điều này có thể được thực hiện bằng một tệp tạm thời hoặc ...
comm -2 -3 <(sort file1) <(sort file2) > file3
miễn là shell của bạn hỗ trợ thay thế quy trình (bash thì có).
comm -23
Tiện ích Unix diff
có nghĩa là cho chính xác mục đích này.
$ diff -u file1 file2 > file3
Xem sách hướng dẫn và Internet để biết các tùy chọn, các định dạng đầu ra khác nhau, v.v.
Hãy xem xét điều này:
tệp a.txt:
abcd
efgh
tệp b.txt:
abcd
Bạn có thể tìm thấy sự khác biệt với:
diff -a --suppress-common-lines -y a.txt b.txt
Đầu ra sẽ là:
efgh
Bạn có thể giới hạn lại đầu ra trong tệp đầu ra (c.txt) bằng cách sử dụng:
diff -a --suppress-common-lines -y a.txt b.txt > c.txt
Điều này sẽ trả lời câu hỏi của bạn:
"... chứa các dòng trong file1 không có trong file2."
-d
, điều này sẽ cố gắng diff
hết sức để tìm ra sự khác biệt nhỏ nhất có thể. -i
, -E
, -w
, -B
Và --suppress-blank-empty
cũng có thể hữu ích đôi khi, mặc dù không phải lúc nào. Nếu bạn không biết điều gì phù hợp với trường hợp sử dụng của mình, hãy thử diff --help
trước (thường là một ý kiến hay khi bạn không biết lệnh có thể làm gì).
Đôi khi diff
là tiện ích bạn cần, nhưng đôi khi join
lại thích hợp hơn. Các tệp cần được sắp xếp trước hoặc, nếu bạn đang sử dụng trình bao hỗ trợ thay thế quy trình như bash, ksh hoặc zsh, bạn có thể thực hiện sắp xếp nhanh chóng.
join -v 1 <(sort file1) <(sort file2)
Thử
sdiff file1 file2
Nó thường hoạt động tốt hơn nhiều trong hầu hết các trường hợp đối với tôi. Bạn có thể muốn sắp xếp các tệp trước, nếu thứ tự các dòng không quan trọng (ví dụ: một số tệp cấu hình văn bản).
Ví dụ,
sdiff -w 185 file1.cfg file2.cfg
sdiff <(sort file1) <(sort file2)
)
Nếu bạn cần giải quyết vấn đề này bằng coreutils, câu trả lời được chấp nhận là tốt:
comm -23 <(sort file1) <(sort file2) > file3
Bạn cũng có thể sử dụng sd (khác dòng), không yêu cầu sắp xếp cũng như xử lý thay thế và hỗ trợ các luồng vô hạn, như vậy:
cat file1 | sd 'cat file2' > file3
Có lẽ không có nhiều lợi ích về ví dụ này, nhưng vẫn xem xét nó; trong một số trường hợp, bạn sẽ không thể sử dụng comm
cũng grep -F
như không diff
.
Đây là một bài đăng trên blog tôi đã viết về các luồng khác nhau trên thiết bị đầu cuối, giới thiệu sd.
Nhiều câu trả lời đã có, nhưng không có câu trả lời nào trong số đó là IMHO hoàn hảo. Câu trả lời của Thanatos để lại một số ký tự thừa trên mỗi dòng và câu trả lời của Sorpigal yêu cầu các tệp phải được sắp xếp hoặc sắp xếp trước, điều này có thể không đầy đủ trong mọi trường hợp.
Tôi nghĩ rằng cách tốt nhất để nhận được các dòng có (không chars thêm, không tái đặt hàng) khác nhau và không có gì khác là sự kết hợp của diff
, grep
và awk
(hoặc tương đương).
Nếu các dòng không chứa bất kỳ "<" nào, thì một dòng lót ngắn có thể là:
diff urls.txt* | grep "<" | sed 's/< //g'
nhưng điều đó sẽ loại bỏ mọi trường hợp của "<" (nhỏ hơn, khoảng trắng) khỏi các dòng, điều này không phải lúc nào cũng OK (ví dụ: mã nguồn). Tùy chọn an toàn nhất là sử dụng awk:
diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'
Một lớp lót này khác biệt cả hai tệp, sau đó lọc ra đầu ra kiểu ed của khác biệt, sau đó loại bỏ dấu "<" mà khác biệt thêm vào. Điều này hoạt động ngay cả khi các dòng chứa một số "<".
diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt
Tôi đã thử gần như tất cả các câu trả lời trong chủ đề này, nhưng không có câu nào hoàn thành. Sau một vài con đường mòn ở trên một đã làm việc cho tôi. diff sẽ cung cấp cho bạn sự khác biệt nhưng với một số charas đặc biệt không mong muốn. trong đó các dòng khác biệt thực tế của bạn bắt đầu bằng '>'. nên bước tiếp theo là grep dòng bắt đầu với '>' và sau đó bằng cách loại bỏ cùng với sed .
<
. Bạn sẽ thấy điều này nếu bạn hoán đổi thứ tự của các tệp đầu vào. Ngay cả khi bạn đã làm điều này, bạn sẽ muốn bỏ qua grep
bằng cách sử dụng thêm sed: `diff a1 a2 | sed '/> / s ///' 'Điều này vẫn có thể ngắt các dòng có chứa >
hoặc <
trong tình huống phù hợp và vẫn để lại các dòng phụ mô tả số dòng. Nếu bạn muốn thử phương pháp này một cách tốt hơn sẽ là: diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'
.