วิธีการแสดงเส้นร่วมกัน (reverse diff)?


170

ฉันมีชุดไฟล์ข้อความที่ฉันต้องการรู้บรรทัดเหมือนกันมากกว่าบรรทัดที่แตกต่างกัน บรรทัดคำสั่ง unix หรือ windows นั้นใช้ได้

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)

บาร์:

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

ดังนั้นเมื่อให้ทั้งสองไฟล์ด้านบนผลลัพธ์ของยูทิลิตี้ที่ต้องการจะคล้ายกับfile1:line_number, file2:line_number == matching text (เพียงข้อเสนอแนะฉันไม่สนใจว่าไวยากรณ์คืออะไร):

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

ขอบคุณ


@ChristopherSchultz ความผิดพลาดของฉัน บรรทัดที่ 1 ในตัวอย่างที่ 1 ควรตรงกับบรรทัดสุดท้ายในตัวอย่างที่ 2 ขอบคุณสำหรับการจับความผิดพลาด; เปลี่ยนแปลง
แมตต์วิลคี

1
อีกคำถามที่คล้ายกันพร้อมคำตอบที่ดี: unix.stackexchange.com/questions/1079/…
MortezaE

คำตอบ:


210

บนระวัง * คุณสามารถใช้การสื่อสาร คำตอบสำหรับคำถามคือ:

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

นี่คือการใช้งานเต็มรูปแบบของ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. 

โปรดทราบว่าการเรียงลำดับไฟล์ก่อนใช้งานเป็นสิ่งสำคัญเช่นที่ระบุไว้ใน man pages


3
comm [-1] [-2] [-3] file1 file2 -1 ระงับคอลัมน์เอาต์พุตของบรรทัดที่ไม่ซ้ำกับ file1 -2 ระงับคอลัมน์เอาต์พุตของบรรทัดที่ไม่ซ้ำกับ file2 -3 หยุดคอลัมน์เอาต์พุตของบรรทัดที่ทำซ้ำใน file1 และ file2
ojblass

@ojblass: เพิ่มสิ่งนี้ในคำตอบ
แมตต์เจ

6
ฉันค้นพบว่ามันเป็นสิ่งสำคัญที่ไฟล์จะถูกจัดเรียงก่อนใช้งานคอม อาจเพิ่มเข้าไปในคำตอบ
แมตต์วิลคี

11
คำตอบสั้น ๆ สำหรับคำถาม: comm -1 -2 file1 file2
greggles

6
คุณสามารถใช้สิ่งนี้หากไฟล์ของคุณไม่ได้ถูกจัดเรียง: comm -1 -2 <(ชื่อไฟล์เรียง 1) <(เรียงชื่อไฟล์เรียง 2)
Kevin Wheeler

56

พบคำตอบนี้เมื่อ คำถามที่ระบุว่าเป็นที่ซ้ำกัน ฉันพบว่า grep เป็นมิตรกับผู้ดูแลระบบมากกว่า comm ดังนั้นหากคุณต้องการชุดของบรรทัดที่ตรงกัน (เช่นมีประโยชน์สำหรับการเปรียบเทียบ CSVs) เพียงแค่ใช้

grep -F -x -f file1 file2

หรือเวอร์ชั่น fgrep ที่ง่ายขึ้น

fgrep -xf file1 file2

นอกจากนี้คุณสามารถใช้file2*เพื่อ glob และค้นหาบรรทัดที่เหมือนกันกับไฟล์หลายไฟล์แทนที่จะเป็นเพียงสองไฟล์

รูปแบบที่มีประโยชน์อื่น ๆ ได้แก่

  • -n ตั้งค่าสถานะเพื่อแสดงหมายเลขบรรทัดของแต่ละบรรทัดที่จับคู่
  • -c เพื่อนับจำนวนบรรทัดที่ตรงกันเท่านั้น
  • -vเพื่อแสดงเฉพาะบรรทัดใน file2ที่แตกต่างกัน (หรือใช้diff)

การใช้commจะเร็วกว่า แต่ความเร็วนั้นมาจากการจัดเรียงไฟล์ของคุณเสียก่อน มันไม่มีประโยชน์อย่างมากในฐานะ 'reverse diff'


ขอบคุณไรเดอร์สิ่งนี้มีประโยชน์มากกว่าการสื่อสารกับคนมากมาย คุณควรเชื่อมโยงไปยังคำตอบของแหล่งข้อมูล (มีมากกว่าครึ่งโหลเชื่อมโยงใน Q ในการนำทางด้านขวามือมันเป็นบิตของการค้นหา) นอกจากนี้ยังเป็นการดีที่จะทราบว่า grep ทำอะไรได้ดีกับอินพุตที่จัดเรียงไม่ซ้ำกันและแตกต่างกันและสามารถพิมพ์หมายเลขบรรทัดของการแข่งขันได้
แมตต์วิลคี

1
@mattwilkie ฉันรู้สึกว่าจำเป็นที่จะต้องกลับมาอีกครั้งและชี้แจงการใช้งาน-vธงหลังจากที่ฉันเล็ดรอดด้วยตัวเอง สมมติว่าคุณมีไฟล์ csv สองไฟล์ file1 และ file2 และมีทั้งแถวที่ทับซ้อนกันและไม่ทับซ้อนกัน หากคุณต้องการทั้งหมดและมีเพียงไม่ทับซ้อนกันเป็นแถวโดยใช้fgrep -v file1 file2เพียงจะกลับแถวที่ไม่ทับซ้อนกันใน file2, และไม่มีแถวที่ไม่ทับซ้อนกันเพิ่มเติมใน file1 สิ่งนี้อาจเห็นได้ชัดสำหรับบางคน แต่ควรระบุให้ชัดเจนกว่าการตีความความเสี่ยงที่ผิดพลาด ในกรณีนี้การเรียงลำดับไฟล์และการใช้commยังคงเป็นตัวเลือกที่ดีกว่า
ไรเดอร์

1
ขอบคุณที่กลับมาและอธิบายไรเดอร์ ความสนใจเป็นพิเศษถูกบันทึกไว้และชื่นชม (ทั้งหมด t0o ง่ายต่อการปล่อยให้สิ่งเก่าหลุดมือไป!) ฉันได้เปลี่ยนคำตอบที่ยอมรับแล้วเนื่องจาก comm เป็นตัวเลือกที่ชัดเจนของชุมชนแม้ว่าโดยส่วนตัวแล้วฉันยังใช้สิ่งนี้เมื่อการเรียงลำดับเป็นค่าใช้จ่ายที่ไม่พึงประสงค์
แมตต์วิลคี

2
ภาวะแทรกซ้อนอื่นเมื่อใช้grep: บรรทัดว่างใด ๆ ในไฟล์แรกจะจับคู่ทุกบรรทัดในไฟล์ที่สอง ตรวจสอบให้แน่ใจว่าfile1ไม่มีบรรทัดว่างเปล่าหรือดูเหมือนว่าไฟล์จะเหมือนกัน
Christopher Schultz

grep -Fxfมันสำหรับฉัน
loxaxs

35

ถูกถามที่นี่ก่อน: คำสั่ง Unix เพื่อค้นหาบรรทัดที่พบบ่อยในสองไฟล์

คุณสามารถลองด้วย perl (เครดิตได้ที่นี่ )

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

1
ขอบคุณ ฉันต้องการยอมรับคำตอบทั้งสองเนื่องจาก perl one liner เป็นแพลตฟอร์มข้าม Comm ได้รับการพยักหน้าเพราะมันง่ายกว่า
แมตต์วิลคี

1
สมบูรณ์ การใช้เทอร์มินัล cygwin บน windows และcommไม่พร้อมใช้งาน นี่เป็นทางเลือกที่สมบูรณ์แบบ
Qix - MONICA ถูกยกเลิก

3
สิ่งนี้ไม่สนใจว่าจะเรียงลำดับบรรทัดอย่างไร มันแม่นยำมากกว่าการสื่อสาร
enl8enmentnow

1
คำอธิบายอยู่ที่นี่: stackoverflow.com/questions/17552789/…
Chris Koknat

17

ฉันเพิ่งเรียนรู้คำสั่ง comm จากเธรดนี้ แต่ต้องการเพิ่มอะไรพิเศษ: ถ้าไฟล์ไม่ถูกเรียงและคุณไม่ต้องการสัมผัสไฟล์ต้นฉบับคุณสามารถไพพ์ outptut ของคำสั่ง sort ได้ ทำให้ไฟล์ต้นฉบับไม่เปลี่ยนแปลง ทำงานในทุบตีฉันไม่สามารถพูดเกี่ยวกับเปลือกหอยอื่น ๆ

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

สิ่งนี้สามารถขยายได้เพื่อเปรียบเทียบเอาต์พุตคำสั่งแทนที่จะเป็นไฟล์:

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

9

วิธีที่ง่ายที่สุดที่จะทำคือ:

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

ไม่จำเป็นต้องทำการเรียงลำดับไฟล์


1
ซึ่งแตกต่างจากคำตอบส่วนใหญ่ที่นี่ที่ช่วยให้คุณสามารถสร้างแม่แบบแหล่งที่มา ฉันมีไฟล์สองไฟล์ที่สร้างจาก wrapper เดียวกันโดยมีข้อความที่แตกต่างกันแทรกอยู่สองสามจุด คำตอบนี้ทำให้ฉันสามารถกู้เสื้อคลุมได้
Lucas Gonze

1

สำหรับข้อมูลฉันทำเครื่องมือเล็กน้อยสำหรับ Windows ที่ทำสิ่งเดียวกันมากกว่า "grep -F -x -f file1 file2" (เนื่องจากฉันไม่พบสิ่งใดเทียบเท่ากับคำสั่งนี้บน Windows)

นี่คือ: http://www.nerdzcore.com/?page=commonlines

การใช้งานคือ "CommonLines inputFile1 inputFile2 outputFile"

ซอร์สโค้ดยังมีอยู่ (GPL)


1

ในWindowsคุณสามารถใช้Powershell Script กับCompareObject

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

CompareObject:

  • IncludeEqual โดยไม่มี - ยกเว้นที่แตกต่างกัน: ทุกอย่าง
  • ExcludeDifferent ที่ไม่มี -InclueEqual: ไม่มีเลย
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.