2013-01-23 19 views
61

Tôi có hai tệp (giả sử a.txtb.txt), cả hai tệp đều có một danh sách tên. Tôi đã chạy sort trên cả hai tệp.Tìm các dòng từ một tệp không có trong tệp khác

Bây giờ tôi muốn tìm các dòng từ a.txt không có trong b.txt.

(Tôi đã dành nhiều thời gian để tìm ra câu trả lời cho câu hỏi này, vì vậy chứng minh điều này để tham khảo trong tương lai)

Trả lời

101

Lệnh bạn phải sử dụng không phải là diff nhưng comm

comm -23 a.txt b.txt 

Theo mặc định, comm kết quả đầu ra 3 cột: chỉ còn lại, chỉ phải, cả hai. Các thiết bị chuyển mạch -1, -2-3 chặn các cột này.

Vì vậy, -23 ẩn phải chỉcả cột, cho thấy dòng mà chỉ xuất hiện trong lần đầu tiên (trái) tập tin.

Nếu bạn muốn tìm đường xuất hiện trong cả hai, bạn có thể sử dụng -12, mà ẩn trái chỉphải chỉ cột, để lại cho bạn chỉ là cột cả.

+9

Tôi sẽ thêm rằng điều này chỉ hoạt động nếu cả hai tập tin được sắp xếp. (Tôi biết OP đã đề cập đến ông đã sắp xếp các tệp, nhưng nhiều người, tôi đã bao gồm, đọc tiêu đề câu hỏi và sau đó chuyển đến câu trả lời) – user247866

+1

@ user247866: May mắn thay comm là loại đủ để cho bạn biết nếu họ không được sắp xếp :) – marlar

20

Câu trả lời đơn giản không hiệu quả đối với tôi vì tôi không nhận ra dòng comm phù hợp cho dòng, vì vậy các dòng trùng lặp trong một tệp sẽ được in dưới dạng không tồn tại trong tệp còn lại. Ví dụ, nếu file1 chứa:

Alex 
Bill 
Fred 

Và file2 chứa:

Alex 
Bill 
Bill 
Bill 
Fred 

Sau đó comm -13 file1 file2 sẽ đầu ra:

Bill 
Bill 

Trong trường hợp của tôi, tôi muốn biết duy nhất mà tất cả các chuỗi trong tệp 2 tồn tại trong tệp 1, bất kể số lần dòng đó xảy ra trong mỗi tệp.

Giải pháp 1: sử dụng -u (unique) cờ để sort:

comm -13 <(sort -u file1) <(sort -u file2)

Giải pháp 2: (người đầu tiên "làm việc" câu trả lời tôi thấy) từ unix.stackexchange:

fgrep -v -f file1 file2

Lưu ý rằng nếu tệp 2 chứa dupli dòng cate không tồn tại ở tất cả trong file1, fgrep sẽ xuất ra mỗi dòng trùng lặp.Cũng lưu ý rằng các thử nghiệm hoàn toàn phi khoa học của tôi trên một máy tính xách tay cho một bộ dữ liệu (khá lớn) cho thấy Giải pháp 1 (sử dụng comm) nhanh gấp gần 5 lần so với Giải pháp 2 (sử dụng fgrep).

+0

I có các tệp của tôi được sắp xếp và chuyển qua uniq. Anyways cảm ơn cho các giải pháp khác. – Sudar

2

Tôi không chắc chắn tại sao nó được cho là diff không nên được sử dụng. Tôi sẽ sử dụng nó để so sánh hai tập tin và sau đó đầu ra chỉ có các dòng có trong tập tin bên trái nhưng không phải trong một bên phải. ngành, nghề đó được đánh dấu bởi diff với < nên nó cũng đủ để grep biểu tượng đó vào đầu dòng

diff a.txt b.txt | grep \^\< 
+1

Bạn có thể sử dụng 'diff --new-line-format = --unchanged-line-format = a.txt b.txt' để chặn in các dòng mới và không thay đổi. –

3

Trong trường hợp các tập tin sẽ không được sắp xếp nào, bạn có thể sử dụng:

comm -23 <(sort a.txt) <(sort b.txt) 
Các vấn đề liên quan