เอาท์พุทบรรทัดทั่วไป (ความเหมือน) ของไฟล์ข้อความสองไฟล์ (ตรงกันข้ามกับ diff)?


21

Diff เป็นเครื่องมือที่ยอดเยี่ยมในการแสดงการเปลี่ยนแปลงระหว่างสองไฟล์ แต่วิธีการแสดงความคล้ายคลึงกันของไฟล์ข้อความสองไฟล์ (ในขณะที่ละเว้นความแตกต่าง)?

Ie ตัวอย่างอินพุต:

a:
Foo Bar
X
Hello
World
42

b:
Foo Baz
Hello
World
23

Pseudo output (บางอย่างเช่นนี้):

@@ 2,3
=Hello World

เพียงแค่เรียงลำดับทั้งไฟล์และการใช้งานคอมไม่เพียงพอเพราะในกรณีนี้ข้อมูลเส้นจะหายไป

คำตอบ:


24

วิธีการเกี่ยวกับการใช้ diff แม้ว่าคุณไม่ต้องการ diff ลองสิ่งนี้:

diff --unchanged-group-format='@@ %dn,%df 
  %<' --old-group-format='' --new-group-format='' \
  --changed-group-format='' a.txt b.txt

นี่คือสิ่งที่ฉันได้รับจากข้อมูลตัวอย่างของคุณ:

$ cat a.txt 
Foo Bar
X
Hello
World
42
$ cat b.txt 
Foo Baz
Hello
World
23
$ diff --unchanged-group-format='@@ %dn,%df
%<' --old-group-format='' --new-group-format='' \
  --changed-group-format='' a.txt b.txt
@@ 2,3
Hello
World

2
คุณสามารถหลีกเลี่ยงการฝังบรรทัดใหม่ตามตัวอักษรเช่นนี้:...%df'$'\n''%<'...
หยุดชั่วคราวจนกว่าจะมีประกาศเพิ่มเติม

1
คุณสามารถทำเช่นนี้ได้: ... --unchanged-group-format="@@ %dn,%df%c'\012'%<" ...(สังเกตเครื่องหมายคำพูดคู่)
หยุดชั่วคราวจนกว่าจะมีประกาศเพิ่มเติม

สิ่งที่ยอดเยี่ยม! ฉันไม่รู้จักตัวเลือกเหล่านี้เพราะฉันเพิ่งดูหน้าคนต่าง ...
maxschlepzig

ฉันใช้ diff --version diff (GNU diffutils) 2.8.1 และฉันได้รับข้อผิดพลาดดังต่อไปนี้: diff: ตัวเลือกสไตล์เอาต์พุตที่ขัดแย้งกัน diff: ลอง `diff - help 'สำหรับข้อมูลเพิ่มเติม
Sujay

ฉันได้รับ "ข้อผิดพลาด: ต่าง: ตัวเลือกสไตล์ผลลัพธ์ที่ขัดแย้งกันต่างกัน" เพราะฉันมีนามแฝงต่างที่กำหนดไว้ ใช้which diffเพื่อดูว่านี่เป็นปัญหาของคุณหรือไม่
justinjhendrick

14
grep -Fxf file1 file2

-Fหมายถึงจับคู่สตริงธรรมดา (ไม่ใช่ regexps) -xหมายถึงเฉพาะการจับคู่ทั้งบรรทัด-fหมายถึงใช้ 'รูปแบบ' (เช่นบรรทัด) จากไฟล์ที่ตั้งชื่อเป็นอาร์กิวเมนต์


3
ไม่ได้-fและ-Fแลกเปลี่ยน? อย่างน้อยในgrepรุ่นของฉันก็เป็นอย่างนั้น ฉันต้องfile2ป้อนข้อมูลเพื่อ-fโต้แย้งเช่นcat file1 | grep -Fxf file2นี้แล้วใช้ได้
Birei

มันไม่ได้ผลสำหรับฉัน
Chaminda Bandara

7

commสามารถใช้ได้. man commสำหรับตัวเลือกทั้งหมด แต่คุณจะต้องใช้comm -12 ...เพื่อแสดงเฉพาะบรรทัดที่มีอยู่ในทั้งสองอินพุต

เมื่อคนอื่นชี้ให้เห็นคุณจะต้องส่งผ่านข้อมูลของคุณsortก่อน


1
อืมมันใช้ได้กับสายทั่วไปที่อยู่ที่หมายเลขบรรทัดเดียวกันในทั้งสองไฟล์
maxschlepzig

2
ดูเหมือนว่าจะเป็นไฟล์ที่เรียงลำดับเท่านั้นและจะไม่ให้ผลลัพธ์ที่มีประโยชน์สำหรับ usecase ของ OP ตัวอย่างของเขา: $ comm -12 ab Hello World comm: ไฟล์ 1 ไม่เรียงลำดับ comm: ไฟล์ 2 ไม่ได้เรียงตามลำดับ
Marcel Stimberg

@maxschlepzig: คุณควรเรียงไฟล์ของคุณก่อนส่งให้คอม
Hemant

2
โดยการเรียงลำดับคุณจะกำจัดข้อมูลทั้งหมดในตำแหน่งของบรรทัดทั่วไปแม้ว่า คุณจะไม่เรียงลำดับไฟล์ก่อนที่จะเปรียบเทียบกับ diff เช่นกัน
Marcel Stimberg

7

ฉันไม่คิดว่าจะมีคำสั่งเดียวที่ทำในสิ่งที่คุณต้องการให้ทำ คุณสามารถพยายามที่จะรวมการส่งออกของdiffที่มีgrepแต่ หากไฟล์ข้อความของคุณมีไม่มีของตัวละคร|, <, >ต่อไปนี้จะช่วยให้คุณมีการส่งออกที่มีประโยชน์ค่อนข้าง:

$ diff --side-by-side a b | grep -n -v "[|<>]"
3:Hello                             Hello
4:World                             World

ลองนี้:diff --width=155 --left-column --side-by-side a b | grep -n -v '|' | sed 's/ *($//'
หยุดชั่วคราวจนกว่าจะมีประกาศ

ที่ดูดีกว่า - แต่คุณต้องรวม <และ> ใน grep เพื่อกำจัดบรรทัดที่เพิ่มในทั้งสองไฟล์
Marcel Stimberg

2

Dick Grune เขียนกลุ่มเครื่องมือสำหรับสิ่งนี้:

http://dickgrune.com/Programs/similarity_tester/

มีรุ่นที่แยกไวยากรณ์ของภาษาต่างๆเพื่อให้สิ่งต่าง ๆ เช่นตัวแปรที่ถูกเปลี่ยนชื่อสามารถเห็นได้ว่าไม่เปลี่ยนแปลง

มันบรรจุsimilarity-testerอยู่ใน Debian และ Ubuntu

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