ฉันจะได้รับความแตกต่างเพื่อแสดงเฉพาะบรรทัดที่เพิ่มและลบได้อย่างไร หาก diff ไม่สามารถทำได้เครื่องมือจะทำอะไรได้บ้าง


69

ฉันจะได้รับความแตกต่างเพื่อแสดงเฉพาะบรรทัดที่เพิ่มและลบได้อย่างไร หาก diff ไม่สามารถทำได้เครื่องมือจะทำอะไรได้บ้าง


2
คุณต้องกำหนดความหมายของการเพิ่มและลบที่ดีขึ้น โดยเฉพาะการเปลี่ยนแปลงบรรทัดสามารถ? ถ้าเป็นเช่นนั้นคุณต้องการให้มีการจัดการสายการเปลี่ยนแปลงอย่างไร หากคุณทำการตรวจสอบโดยใช้การวางสายอย่างเคร่งครัดการเปลี่ยนบรรทัดจะเหมือนกับบรรทัดเก่าที่ถูกลบออกและมีการเพิ่มบรรทัดใหม่ ตัวอย่างเช่นควรจัดการกับบรรทัดที่แบ่งเป็นสองอย่างไร เมื่อสอง 1 บรรทัดเปลี่ยนไปหรือไม่ มีการเปลี่ยนแปลง 2 บรรทัด? ลบ 1 บรรทัดและเพิ่มอีก 2 บรรทัดแล้วหรือยัง หากคุณไม่สามารถรับประกันได้ว่าบรรทัดจะไม่เปลี่ยนแปลงเพียงแค่เพิ่มและลบฉันคิดว่านี่เป็นอีกครั้งที่จะล้มเหลวโดยไม่มีคำจำกัดความที่ดีกว่า
Christopher Cashell

ฉันพบคำถามที่ค่อนข้างชัดเจน แต่อย่างน้อยหนึ่งการตีความของคำถามสามารถตอบได้ด้วยdiff A B | grep '^[<>]'
kasperd

commคุณอาจจะมองหา
เจนนี่ D

@ChristopherCashell เขาหมายถึงละเว้นการเรียงลำดับ; ปัญหาที่พบบ่อยโดยทั่วไป โดยปกติแล้วสิ่งนี้จะกระทำโดยการเรียงลำดับเซ็กเมนต์ (บรรทัด) ในแต่ละด้านก่อนทำ diff ทั่วไป
Pacerier

@Pierier คุณแน่ใจหรือไม่? หรือคุณคาดเดา ไม่มีการกล่าวถึงหรือเรียงลำดับการเรียงลำดับหรือค้นหาในคำถาม คำถามนี้ไม่ชัดเจนและสามารถตีความได้หลายวิธี โดยไม่ทราบว่าสิ่งที่เขาถามนั้นคืออะไรเรากำลังตั้งสมมติฐานและเสนอวิธีแก้ปัญหาที่อาจจะหรืออาจจะไม่แก้ปัญหาที่เกิดขึ้นจริง นอกจากนี้ความคิดเห็นของผู้โพสต์ดั้งเดิมเกี่ยวกับคำตอบข้อใดข้อหนึ่งแสดงว่าสิ่งนี้ไม่เกี่ยวข้องกับการเรียงลำดับ มันเกี่ยวข้องกับความหมายของ "การเพิ่มและการลบ" กับ "การเปลี่ยนแปลง"
Christopher Cashell

คำตอบ:


82

ลองใช้คอม

อีกวิธีในการดู:

  • แสดงบรรทัดที่มีอยู่ในไฟล์ a: (เช่นสิ่งที่ถูกลบออกจาก a)

    comm -23 a b
    
  • แสดงบรรทัดที่มีอยู่ในไฟล์ b เท่านั้น: (คือสิ่งที่ถูกเพิ่มใน b)

    comm -13 a b
    
  • แสดงบรรทัดที่มีอยู่ในไฟล์เดียวหรืออย่างอื่น: (แต่ไม่ใช่ทั้งคู่)

    comm -3 a b | sed 's/^\t//'
    

(คำเตือน: หากไฟล์aมีบรรทัดที่ขึ้นต้นด้วย TAB ไฟล์นั้น (TAB แรก) จะถูกลบออกจากเอาต์พุต)

จัดเรียงไฟล์เท่านั้น

หมายเหตุ:ไฟล์ทั้งสองจะต้องเรียงลำดับเพื่อcommให้ทำงานได้อย่างถูกต้อง หากยังไม่ได้เรียงคุณควรจัดเรียง:

sort <a >a.sorted
sort <b >b.sorted
comm -12 a.sorted b.sorted

หากไฟล์มีความยาวมากอาจเป็นภาระมากเพราะต้องใช้การคัดลอกเพิ่มเติมดังนั้นจึงเพิ่มพื้นที่ดิสก์เป็นสองเท่า


5
เพียงแค่ต้องการเพิ่มว่าทั้งสองไฟล์จะต้องมีการเรียงลำดับ (กรณีที่สำคัญ) สำหรับวิธีการแก้ปัญหานี้เพื่อให้ได้ผลลัพธ์ที่ถูกต้อง
marmor

1
ในกระสุนที่ทันสมัยพอคุณสามารถจัดเรียงแนวเดียวกับcomm -12 <(sort a) <(sort b)
Joshua Huber

14

commอาจทำสิ่งที่คุณต้องการ จากหน้าคนของมัน:

รายละเอียด

เปรียบเทียบไฟล์ที่เรียงลำดับ FILE1 และ FILE2 ทีละบรรทัด

ไม่มีตัวเลือกให้สร้างเอาต์พุตสามคอลัมน์ คอลัมน์หนึ่งมีบรรทัดที่ไม่ซ้ำกับ FILE1 คอลัมน์ที่สองมีบรรทัดที่ไม่ซ้ำกับ FILE2 และคอลัมน์ที่สามมีบรรทัดที่ใช้ร่วมกันกับทั้งสองไฟล์

คอลัมน์เหล่านี้เป็น suppressable ด้วย-1, -2และ-3ตามลำดับ

ตัวอย่าง:

[root@dev ~]# cat a
common
shared
unique

[root@dev ~]# cat b
common
individual
shared

[root@dev ~]# comm -3 a b
    individual
unique

และถ้าคุณต้องการเส้นที่ไม่ซ้ำใครและไม่สนใจว่าไฟล์พวกมันอยู่ใน:

[root@dev ~]# comm -3 a b | sed 's/^\t//'
individual
unique

ดังที่ man page กล่าวไฟล์ต้องถูกจัดเรียงไว้ล่วงหน้า


9

ในการแสดงการเพิ่มและการลบโดยไม่มีบริบทหมายเลขบรรทัด +, -, <,>! ฯลฯ คุณสามารถใช้ diff แบบนี้:

diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt 

ตัวอย่างเช่นกำหนดสองไฟล์:

a.txt

Common
Common
A-ONLY
Common

b.txt

Common
B-ONLY
Common
Common

คำสั่งต่อไปนี้จะแสดงบรรทัดที่ถูกลบออกจาก a หรือเพิ่มใน b:

diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt 

เอาท์พุท:

B-ONLY
A-ONLY

คำสั่งที่แตกต่างกันเล็กน้อยนี้จะแสดงบรรทัดที่ถูกลบออกจาก a.txt:

diff --changed-group-format='%<' --unchanged-group-format='' a.txt b.txt 

เอาท์พุท:

A-ONLY

ในที่สุดคำสั่งนี้จะแสดงบรรทัดที่เพิ่มเข้าไปใน a.txt

diff --changed-group-format='%>' --unchanged-group-format='' a.txt b.txt 

เอาท์พุต

B-ONLY

2

นั่นคือสิ่งที่แตกต่างกันไปตามค่าเริ่มต้น ... บางทีคุณอาจต้องเพิ่มค่าสถานะเพื่อละเว้นช่องว่าง

diff -b -B

ควรละเว้นบรรทัดว่างและจำนวนช่องว่างที่แตกต่างกัน


1
ไม่มันจะแสดงบรรทัดที่ถูกเปลี่ยนเช่นกัน (บรรทัดที่มีอักขระหรือสี่ตัวที่แตกต่างกัน) ฉันต้องการเส้นที่มีอยู่ทางซ้ายหรือขวาเท่านั้น
C. Ross

2
คุณสามารถยืนยันได้ว่าเวอร์ชันที่แตกต่างกันของไฟล์ CHANGED แต่ละไฟล์มีอยู่ทางซ้ายหรือขวาเท่านั้น
markdrayton

2
ไม่มีวิธีใดที่ diff (หรือเครื่องมืออื่น ๆ ) จะบอกได้อย่างน่าเชื่อถือว่ามีอะไรเปลี่ยนแปลงและบรรทัดที่ถูกลบจะถูกแทนที่ด้วยบรรทัดใหม่
เซียน

1
ในทางเทคนิค diff ปฏิบัติกับบรรทัด "ที่ถูกเปลี่ยนแปลง" ราวกับว่าบรรทัดต้นฉบับถูกลบและเพิ่มบรรทัดใหม่ ... ดังนั้นโดยทางเทคนิคแล้วมันจะแสดงเฉพาะคุณที่เพิ่มและลบบรรทัดเท่านั้น
KFro

2

ไม่diffไม่ได้แสดงความแตกต่างระหว่างสองไฟล์ในแบบที่คิด มันสร้างลำดับของคำสั่งแก้ไขสำหรับเครื่องมือที่ต้องการpatchใช้เพื่อเปลี่ยนไฟล์หนึ่งเป็นอีกไฟล์หนึ่ง

ความยากลำบากในการพยายามทำสิ่งที่คุณกำลังมองหาคือวิธีการกำหนดสิ่งที่ถือเป็นบรรทัดที่มีการเปลี่ยนแปลงเมื่อเทียบกับที่ถูกลบแล้วตามด้วยการเพิ่ม รวมถึงสิ่งที่ต้องทำเมื่อเพิ่มบรรทัดลบและเปลี่ยนแปลงติดกัน


ความคิดของฉันอย่างแน่นอน เปอร์เซ็นต์ของอักขระในบรรทัดต้องเปลี่ยนแปลงเพื่อพิจารณาเป็นอักขระใหม่แทนที่จะเป็นแบบดั้งเดิม ในทางเทคนิคแม้ว่าคุณจะมีตัวละครเหมือนกันก็ตามคุณสามารถพิจารณาว่าเป็น "การเปลี่ยนแปลง" แทนที่จะเป็นการลบและการแทรก
Kamil Kisiel

1
เป็นเวลานานแล้วที่ฉันได้ดูdiffแหล่งที่มา แต่ดูเหมือนว่าฉันจะจำทุกความเคลื่อนไหวของไจแอนต์เพื่อติดตามว่าไฟล์สองไฟล์เข้ากันได้อย่างไรในการซิงค์และฉันคิดว่ามันมีขีด จำกัด ในการเลิกตาม เส้นคือ แต่ฉันจำไม่ได้ว่าการจับคู่แบบอินทราไลน์ใด ๆ ยกเว้น (ตัวเลือก) การยุบพื้นที่สีขาวหรือการละเว้นกรณี หรือ (อาจ) คำที่มีผลต่อ ไม่ว่าในกรณีใด ๆ มันคือทั้งหมดที่เกี่ยวกับpatchและ "vgrep" เพิ่งมาพร้อมสำหรับการนั่ง อาจจะ. ในวันอังคาร.
Dennis Williamson

2

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

นี่เป็นวิธีที่เครื่องมือบรรทัดคำสั่งsdiffทำงานซึ่งแสดงการเปรียบเทียบสองไฟล์ในเทอร์มินัล เส้นที่ถูกเปลี่ยนจะถูกคั่นด้วย | ตัวละคร หากบรรทัดมีอยู่ในไฟล์ A เท่านั้นระบบจะใช้ <เป็นอักขระตัวคั่น หากบรรทัดมีอยู่ในไฟล์ B เท่านั้นระบบจะใช้> เป็นตัวคั่น หากคุณไม่มีอักขระ <และ> ในไฟล์คุณสามารถใช้ตัวเลือกนี้เพื่อแสดงเฉพาะบรรทัดที่เพิ่ม:

sdiff A B | grep '[<>]'

2

ขอบคุณ senarvi ทางออกของคุณ (ไม่ได้รับการโหวต) ทำให้ฉันได้อย่างแม่นยำในสิ่งที่ฉันต้องการหลังจากมองหาอายุในหน้าต่างๆ

ใช้คำตอบของคุณนี่คือสิ่งที่ฉันคิดขึ้นเพื่อรับรายการสิ่งที่เปลี่ยนแปลง / เพิ่ม / ลบ ตัวอย่างใช้ไฟล์ / etc / passwd 2 เวอร์ชันและพิมพ์ชื่อผู้ใช้สำหรับบันทึกที่เกี่ยวข้อง

#!/bin/bash
sdiff passwd1 passwd2 | grep '[|]' | awk -F: '{print "changed: " $1}'
sdiff passwd1 passwd2 | grep '[<]' | awk -F: '{print "deleted: " $1}'
sdiff passwd1 passwd2 | grep '[>]' | awk -F\> '{print $2}' | awk -F: '{print "added: " $1}'

โปรดทราบว่าเนื่องจากความแตกต่างระหว่าง "บรรทัดได้รับการแก้ไข" และ "บรรทัดถูกลบออกและมีการเพิ่มบรรทัดอื่นด้านล่างหรือด้านบน" เป็นความหมาย เครื่องมือ diff แบบข้อความทั่วไปไม่สามารถแยกกรณีเหล่านั้นได้ เป็นผลให้คำตอบตาม sdiff ของคุณไม่สามารถทำงานได้อย่างน่าเชื่อถือในทุกกรณี
Mikko Rantalainen

0

ฉันพบว่ารูปแบบนี้มักจะมีประโยชน์:

diff --changed-group-format='-%<+%>' --unchanged-group-format='' f g

ตัวอย่าง:

printf 'a\nb\nc\nd\ne\nf\ng\n' > f
printf 'a\nB\nC\nd\nE\nF\ng\n' > g
diff --old-line-format=$'-%l\n' \
     --new-line-format=$'+%l\n' \
     --unchanged-line-format='' \
     f g

เอาท์พุท:

-b
-c
+B
+C
-e
-f
+E
+F

ดังนั้นจึงแสดงให้เห็นว่าเส้นเก่าที่มีตามทันทีโดยการขึ้นบรรทัดใหม่ที่สอดคล้องกับ-+

หากเรามีการลบC:

printf 'a\nb\nd\ne\nf\ng\n' > f
printf 'a\nB\nC\nd\nE\nF\ng\n' > g
diff --old-line-format=$'-%l\n' \
     --new-line-format=$'+%l\n' \
     --unchanged-line-format='' \
     f g

ดูเหมือนว่านี้:

-b
+B
+C
-e
-f
+E
+F

รูปแบบเอกสารที่man diff:

       --line-format=LFMT
              format all input lines with LFMT`

และ:

       LTYPE is 'old', 'new', or 'unchanged'.
              GTYPE is LTYPE or 'changed'.

และ:

              LFMT (only) may contain:

       %L     contents of line

       %l     contents of line, excluding any trailing newline

       [...]

คำถามที่เกี่ยวข้อง: https://stackoverflow.com/questions/15384818/how-to-get-the-difference-only-additions-between-two-files-in-linux

ทดสอบใน Ubuntu 18.04


-1

file1:

text670_1
text067_1
text067_2

file2:

text04_1
text04_2
text05_1
text05_2
text067_1
text067_2
text1000_1

ใช้:

diff -y file1 file2

แสดงสองคอลัมน์สำหรับไฟล์ repectives

เอาท์พุท:

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