Có công cụ nào có thể nhận được dòng mà tập tin A chứa, nhưng tập tin B không? Tôi có thể tạo một kịch bản đơn giản với, ví dụ như perl, nhưng nếu một cái gì đó như thế đã tồn tại, tôi sẽ tiết kiệm thời gian của mình kể từ bây giờ.
Có công cụ nào có thể nhận được dòng mà tập tin A chứa, nhưng tập tin B không? Tôi có thể tạo một kịch bản đơn giản với, ví dụ như perl, nhưng nếu một cái gì đó như thế đã tồn tại, tôi sẽ tiết kiệm thời gian của mình kể từ bây giờ.
Câu trả lời:
Đúng. Công grep
cụ tiêu chuẩn để tìm kiếm tệp cho chuỗi văn bản có thể được sử dụng để trừ tất cả các dòng trong một tệp từ tệp khác.
grep -F -x -v -f fileB fileA
Điều này hoạt động bằng cách sử dụng mỗi dòng trong tệpB như một mẫu ( -f fileB
) và coi nó như một chuỗi đơn giản để khớp (không phải là biểu thức chính quy thông thường) ( -F
). Bạn buộc trận đấu diễn ra trên toàn bộ dòng ( -x
) và chỉ in ra những dòng không khớp ( -v
). Do đó, bạn đang in các dòng trong tệpA không chứa cùng dữ liệu với bất kỳ dòng nào trong tệpB.
Nhược điểm của giải pháp này là nó không tính đến thứ tự dòng và nếu đầu vào của bạn có các dòng trùng lặp ở những nơi khác nhau, bạn có thể không nhận được những gì bạn mong đợi. Giải pháp cho điều đó là sử dụng một công cụ so sánh thực sự như diff
. Bạn có thể làm điều này bằng cách tạo một tệp diff với giá trị ngữ cảnh ở 100% các dòng trong tệp, sau đó phân tích cú pháp cho các dòng sẽ bị xóa nếu chuyển đổi tệp A thành tệp B. (Lưu ý lệnh này cũng loại bỏ diff định dạng sau khi nó nhận được đúng dòng.)
diff -U $(wc -l < fileA) fileA fileB | sed -n 's/^-//p' > fileC
-u
Đối số chữ thường thực sự lấy tham số của một số miễn là nó không được theo sau bởi khoảng trắng . Ưu điểm của cách tôi đã có trước đây là nó sẽ hoạt động có hoặc không có giá trị, vì vậy bạn có thể sử dụng một cái gì đó trong thói quen lệnh phụ mà trả về không xuất ra. Chữ hoa '-U' mặt khác yêu cầu một đối số.
diff
đường ống làm việc một điều trị cảm ơn.
grep
cần. Ví dụ:grep -F -x -v -f <(sort fileB) <(sort fileA)
diff
là vị trí trong tệp được tính đến.
Câu trả lời phụ thuộc rất nhiều vào loại và định dạng của các tệp bạn đang so sánh.
Nếu các tệp bạn đang so sánh là các tệp văn bản được sắp xếp, thì công cụ GNU được viết bởi Richard Stallman và Davide McKenzie được gọi comm
có thể thực hiện quá trình lọc mà bạn đang theo dõi. Nó là một phần của coreutils.
Giả sử bạn có 2 tệp sau:
$ cat a
1
2
3
4
5
$ cat b
1
2
3
4
5
6
Các dòng trong tệp b
không có trong tệp a
:
$ comm <(sort a) <(sort b) -3
6
comm
; thật không may, comm
yêu cầu các tệp được sắp xếp
<()
? Nó hoạt động và tôi hiểu nó, nhưng có một cái tên cho sự kỳ lạ này?
<()
còn được gọi là quá trình thay thế .
comm
ban đầu được viết vào khoảng năm 1973 bởi một người nào đó tại Bell Labs, không phải rms. Bạn đang đề cập đến việc triển khai GNU mà sau này rất nhiều. Đã có rất nhiều triển khai khác nhau của các tiện ích Unix trong những năm qua.
từ stackoverflow ...
comm -23 file1 file2
-23 loại bỏ các dòng trong cả hai tệp hoặc chỉ trong tệp 2. Các tệp phải được sắp xếp (chúng nằm trong ví dụ của bạn) nhưng nếu không, hãy chuyển chúng qua sắp xếp trước ...
Xem trang người đàn ông ở đây
Các phương thức grep và comm (with sort) mất nhiều thời gian trên các tệp lớn. SiegeX và ghostdog74 đã chia sẻ hai phương pháp awk tuyệt vời để trích xuất các dòng duy nhất cho một trong hai tệp trên Stack Overflow:
$ awk 'FNR==NR{a[$0]++}FNR!=NR && !a[$0]{print}' file1 file2
$ awk 'FNR==NR{a[$0]++;next}(!($0 in a))' file1 file2
Nếu các tệp lớn và bạn không có thứ tự tùy chỉnh cho các mục nhập của mình, grep sẽ mất quá nhiều thời gian. Một sự thay thế nhanh chóng sẽ là
sort file1 > 1
sort file2 > 2
diff 1 2 | grep "\>" | sed -e 's/> //'
[file2-file1 kết quả để sàng lọc, đường ống đến tập tin, v.v.]
Thay đổi >
để <
có được phép trừ ngược lại.rm 1 2