Làm thế nào để hiển thị các dòng chung (khác diff)?


170

Tôi có một loạt các tệp văn bản mà tôi muốn biết các dòng chung thay vì các dòng khác nhau giữa chúng. Dòng lệnh unix hoặc windows là tốt.

foo:

linux-vdso.so.1 =>  (0x00007fffccffe000)
libvlc.so.2 => /usr/lib/libvlc.so.2 (0x00007f0dc4b0b000)
libvlccore.so.0 => /usr/lib/libvlccore.so.0 (0x00007f0dc483f000)
libc.so.6 => /lib/libc.so.6 (0x00007f0dc44cd000)

quán ba:

libkdeui.so.5 => /usr/lib/libkdeui.so.5 (0x00007f716ae22000)
libkio.so.5 => /usr/lib/libkio.so.5 (0x00007f716a96d000)
linux-vdso.so.1 =>  (0x00007fffccffe000)

Vì vậy, với hai tệp trên mức đầu ra của tiện ích mong muốn sẽ giống với file1:line_number, file2:line_number == matching text (chỉ là một gợi ý, tôi thực sự không quan tâm cú pháp là gì):

foo:1, bar:3 == linux-vdso.so.1 =>  (0x00007fffccffe000)

cảm ơn.


@ChristopherSchultz Sai lầm của tôi. Dòng đầu tiên trong ví dụ đầu tiên được cho là khớp dòng cuối cùng trong ví dụ thứ 2. Cảm ơn vì đã bắt lỗi; thay đổi.
matt wilkie

1
Một câu hỏi tương tự khác với câu trả lời hay: unix.stackexchange.com/questions/1079/ trên
MortezaE

Câu trả lời:


210

Trên * nix, bạn có thể sử dụng comm . Câu trả lời cho câu hỏi là:

comm -1 -2 file1.sorted file2.sorted 
# where file1 and file2 are sorted and piped into *.sorted

Đây là cách sử dụng đầy đủ của comm:

comm [-1] [-2] [-3 ] file1 file2
-1 Suppress the output column of lines unique to file1.
-2 Suppress the output column of lines unique to file2.
-3 Suppress the output column of lines duplicated in file1 and file2. 

Cũng lưu ý rằng điều quan trọng là sắp xếp các tệp trước khi sử dụng comm, như được đề cập trong các trang man.


3
comm [-1] [-2] [-3] file1 file2 -1 Bỏ qua cột đầu ra của các dòng duy nhất cho tệp1. -2 Bỏ qua cột đầu ra của các dòng duy nhất cho tệp2. -3 Bỏ qua cột đầu ra của các dòng được nhân đôi trong tệp1 và tệp2.
ojblass

@ojblass: Đã thêm điều này vào câu trả lời.
Matt J

6
Tôi phát hiện ra điều quan trọng là các tập tin được sắp xếp trước khi sử dụng comm. Có lẽ thêm nó vào câu trả lời.
matt wilkie

11
câu trả lời ngắn cho câu hỏi: comm -1 -2 file1 file2
greggles

6
Bạn có thể sử dụng điều này nếu các tệp của bạn không được sắp xếp: comm -1 -2 <(sort filename1) <(sort filename2)
Kevin Wheeler

56

Tìm thấy câu trả lời này cho một câu hỏi được liệt kê như là một bản sao . Tôi thấy grep thân thiện với quản trị viên hơn comm, vì vậy nếu bạn chỉ muốn tập hợp các dòng phù hợp (ví dụ hữu ích để so sánh CSV), chỉ cần sử dụng

grep -F -x -f file1 file2

hoặc phiên bản fgrep đơn giản hóa

fgrep -xf file1 file2

Thêm vào đó, bạn có thể sử dụng file2*để toàn cầu và tìm kiếm các dòng chung với nhiều tệp, thay vì chỉ hai.

Một số biến thể tiện dụng khác bao gồm

  • -n cờ để hiển thị số dòng của mỗi dòng phù hợp
  • -c chỉ đếm số dòng phù hợp
  • -vđể chỉ hiển thị các dòng trong tệp2 khác nhau (hoặc sử dụng diff).

Sử dụng commnhanh hơn, nhưng tốc độ đó phải trả giá bằng việc phải sắp xếp các tệp của bạn trước. Nó không hữu ích như một "khác biệt ngược".


cảm ơn Ryder, điều này có thể hữu ích hơn nhiều so với comm. Bạn nên liên kết với câu trả lời nguồn (có hơn nửa tá liên kết trong Q trong điều hướng bên phải; đó là một chút công việc để tìm). Cũng thật tuyệt khi biết grep làm tốt như thế nào với đầu vào không được sắp xếp hoặc khác nhau và có thể in số dòng phù hợp tương ứng.
matt wilkie

1
@mattwilkie Tôi cảm thấy cần phải quay lại và làm rõ việc sử dụng -vcờ sau khi tôi tự mình trượt lên. Giả sử bạn có hai tệp csv tệp1 và tệp2 và chúng có cả hai hàng chồng chéo và không chồng lấp. Nếu bạn muốn tất cả và chỉ các hàng không chồng lấp, sử dụng fgrep -v file1 file2sẽ chỉ trả về các hàng không chồng lấp trong tệp2 và không có hàng nào không chồng lấp trong tệp1 . Điều này có thể rõ ràng đối với một số người, nhưng tốt hơn là nói rõ ràng hơn là giải thích sai rủi ro. Trong trường hợp cụ thể này, sắp xếp các tệp và sử dụng commvẫn là lựa chọn tốt hơn.
Ryder

1
Cảm ơn bạn đã quay trở lại và làm rõ Ryder. Sự chú ý thêm được ghi nhận và đánh giá cao (tất cả đều dễ dàng để những thứ cũ biến mất!). Tôi đã chuyển câu trả lời được chấp nhận vì comm rõ ràng là lựa chọn của cộng đồng, mặc dù cá nhân tôi vẫn sử dụng câu này khi sắp xếp là chi phí không mong muốn.
matt wilkie

2
Một sự phức tạp khác khi sử dụng grep: bất kỳ dòng trống nào trong tệp đầu tiên sẽ khớp với mọi dòng trong tệp thứ hai. Đảm bảo file1không có dòng trống, hoặc nó sẽ trông giống như các tệp giống hệt nhau.
Christopher Schultz

grep -Fxfnó là cho tôi
loxaxs 17/03/18

35

Đã được hỏi ở đây trước: Lệnh Unix để tìm các dòng phổ biến trong hai tệp

Bạn cũng có thể thử với perl (tín dụng ở đây )

perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/'  file1 file2

1
cảm ơn. Tôi muốn chấp nhận cả hai câu trả lời, vì perl one liner là nền tảng chéo. Comm nhận được cái gật đầu vì nó đơn giản hơn.
matt wilkie

1
Hoàn hảo. Sử dụng thiết bị đầu cuối cygwin trên windows và commkhông có sẵn. Đây là sự thay thế hoàn hảo.
Qix - MONICA ĐƯỢC PHÂN BIỆT

3
Điều này không quan tâm về cách các dòng được đặt hàng. Nó chính xác hơn comm.
ext8enmentnow

1
Một lời giải thích có ở đây: stackoverflow.com/questions/17552789/
Kẻ

17

Tôi vừa học lệnh comm từ luồng này, nhưng muốn thêm một thứ gì đó: nếu các tệp không được sắp xếp và bạn không muốn chạm vào các tệp gốc, bạn có thể bỏ qua phần ngoài của lệnh sort. Điều này để lại các tập tin ban đầu nguyên vẹn. Hoạt động trong bash, tôi không thể nói về các shell khác.

comm -1 -2 <(sort file1) <(sort file2)

Điều này có thể được mở rộng để so sánh đầu ra lệnh, thay vì các tệp:

comm -1 -2 <(ls /dir1 | sort) <(ls /dir2 | sort)

9

Cách dễ nhất để làm là:

awk 'NR==FNR{a[$1]++;next} a[$1] ' file1 file2

Các tập tin không cần thiết phải được sắp xếp.


1
Điều này không giống như hầu hết các câu trả lời ở đây vì nó cho phép bạn xây dựng lại các mẫu nguồn. Tôi có hai tệp được tạo từ cùng một trình bao bọc, với văn bản khác nhau được chèn tại một vài điểm. Câu trả lời này cho phép tôi khôi phục trình bao bọc.
Lucas G44

1

Chỉ để biết thông tin, tôi đã tạo ra một công cụ nhỏ để Windows thực hiện điều tương tự như "grep -F -x -f file1 file2" (Vì tôi không tìm thấy bất cứ điều gì tương đương với lệnh này trên Windows)

Đây là: http://www.nerdzcore.com/?page=commonlines

Cách sử dụng là "CommonLines inputFile1 inputFile2 outputFile"

Mã nguồn cũng có sẵn (GPL)


1

Trong Windows, bạn có thể sử dụng Tập lệnh Powershell với CompareObject

compare-object -IncludeEqual -ExcludeDifferent -PassThru (get-content A.txt) (get-content B.txt)> MATCHING.txt | Out-Null #Find Matching Lines

So sánhObject:

  • Bao gồmEqual mà không có -ExcludeDifferent: Mọi thứ
  • Không bao gồm khác nhau mà không có -InclueEqual: Không có gì
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.