2012-06-22 39 views
19

Ok, tôi có hai danh sách có liên quan trên hộp linux của tôi trong tập tin văn bản:Bash - Sự khác biệt giữa hai danh sách

/tmp/oldList 
/tmp/newList 

Tôi cần phải so sánh các danh sách này để xem những gì dòng đã gia tăng và những gì dòng bị loại bỏ. Sau đó, tôi cần phải lặp lại các dòng này và thực hiện các tác vụ trên chúng dựa trên việc chúng đã được thêm hay xóa. Làm thế nào để làm điều này trong bash?

+0

Câu hỏi tương tự đã được hỏi 4 ngày trước http://stackoverflow.com/questions/11099894/comparing-2-unsorted-lists-in-linux-listing-the-unique-in-the-second-file/11101143 # 11101143 –

Trả lời

50

Sử dụng lệnh comm(1) để so sánh hai tập tin. Cả hai đều cần phải được sắp xếp, mà bạn có thể làm trước nếu chúng lớn, hoặc bạn có thể làm nó trực tiếp với bash thay thế quá trình.

comm có thể mất một sự kết hợp của những lá cờ -1, -2-3 chỉ ra mà tập tin để ngăn chặn dòng từ (unique nộp 1, độc đáo để nộp 2 hoặc chung cho cả hai).

Để có được dòng duy nhất trong tập tin cũ:

comm -23 <(sort /tmp/oldList) <(sort /tmp/newList) 

Để có được dòng duy nhất trong tập tin mới:

comm -13 <(sort /tmp/oldList) <(sort /tmp/newList) 

Bạn có thể thức ăn đó vào một vòng lặp while read để xử lý mỗi dòng :

while read old ; do 
    ...do stuff with $old 
done < <(comm -23 <(sort /tmp/oldList) <(sort /tmp/newList)) 

và tương tự cho các dòng mới.

4

diff command sẽ thực hiện so sánh cho bạn.

ví dụ

$ diff /tmp/oldList /tmp/newList 

Xem các liên kết trang người đàn ông trên để biết thêm thông tin. Điều này sẽ giải quyết vấn đề đầu tiên của bạn.

+1

Tôi sẽ chỉ nhấn mạnh rằng lệnh 'diff' có vô số tùy chọn để định dạng đầu ra, có thể cung cấp đầu vào thuận tiện cho chương trình sẽ xử lý sự khác biệt. – chepner

+0

@chepner điểm tốt .. nó chắc chắn giá trị kiểm tra ra trang người đàn ông liên kết. – Levon

0

Các bạn đã thử diff

$ diff /tmp/oldList /tmp/newList 

$ man diff 
2

Cân nhắc sử dụng Ruby nếu tập lệnh của bạn cần khả năng đọc.

Để có được dòng duy nhất trong tập tin cũ:

ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')" 

Để có được dòng duy nhất trong tập tin mới:

ruby -e "puts File.readlines('/tmp/newList') - File.readlines('/tmp/oldList')" 

Bạn có thể thức ăn đó vào một thời gian đọc vòng lặp để xử lý mỗi line:

while read old ; do 
    ...do stuff with $old 
done < ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')" 
1

Đây là cũ, nhưng để hoàn thiện, chúng ta nên nói rằng nếu bạn có một bộ thực sự lớn, fastes t giải pháp sẽ là sử dụng diff để tạo ra một kịch bản và sau đó nguồn nó, như thế này:

#!/bin/bash 

line_added() { 
    # code to be run for all lines added 
    # $* is the line 
} 

line_removed() { 
    # code to be run for all lines removed 
    # $* is the line 
} 

line_same() { 
    # code to be run for all lines at are the same 
    # $* is the line 
} 

cat /tmp/oldList | sort >/tmp/oldList.sorted 
cat /tmp/newList | sort >/tmp/newList.sorted 

diff >/tmp/diff_script.sh \ 
    --new-line-format="line_added %L" \ 
    --old-line-format="line_removed %L" \ 
    --unchanged-line-format="line_same %L" \ 
    /tmp/oldList.sorted /tmp/newList.sorted 

source /tmp/diff_script.sh 

Các dòng thay đổi sẽ xuất hiện như đã xóa và thêm vào. Nếu bạn không thích điều này, bạn có thể sử dụng --changed-group-format. Kiểm tra trang hướng dẫn khác.

Các vấn đề liên quan