มีเครื่องมือในการรับบรรทัดในไฟล์ที่ไม่ได้อยู่ในไฟล์อื่นหรือไม่?


110

มีเครื่องมือใดบ้างที่สามารถรับบรรทัดที่ไฟล์ A มี แต่ไฟล์ B ไม่มี? ฉันสามารถสร้างสคริปต์ง่าย ๆ ด้วยเช่น perl แต่ถ้ามีอะไรทำนองนี้มีอยู่แล้วฉันจะประหยัดเวลานับจากนี้



คำตอบ:


159

ใช่. grepเครื่องมือมาตรฐานสำหรับการค้นหาไฟล์สำหรับสตริงข้อความสามารถใช้เพื่อลบบรรทัดทั้งหมดในไฟล์เดียวจากอีกไฟล์หนึ่ง

grep -F -x -v -f fileB fileA

สิ่งนี้ทำงานโดยใช้แต่ละบรรทัดใน fileB เป็นรูปแบบ ( -f fileB) และถือว่าเป็นสตริงธรรมดาที่จะจับคู่ (ไม่ใช่ regex ปกติ) ( -F) คุณบังคับให้การแข่งขันเกิดขึ้นกับทั้งบรรทัด ( -x) และพิมพ์เฉพาะบรรทัดที่ไม่ตรงกัน ( -v) ดังนั้นคุณจึงพิมพ์บรรทัดใน fileA ที่ไม่มีข้อมูลเหมือนกับบรรทัดใด ๆ ใน fileB

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

diff -U $(wc -l < fileA) fileA fileB | sed -n 's/^-//p' > fileC

@ inderpreet99 -uอาร์กิวเมนต์ตัวพิมพ์เล็กจะใช้พารามิเตอร์ของตัวเลขตราบใดที่ไม่เว้นวรรคตามด้วยช่องว่าง ข้อดีของวิธีที่ฉันมีมาก่อนคือมันจะทำงานโดยมีหรือไม่มีค่าดังนั้นคุณสามารถใช้บางอย่างในรูทีนคำสั่งย่อยนั้นที่ส่งคืนไม่ใช่เอาต์พุต ตัวพิมพ์ใหญ่ '-U' ในทางกลับกันจำเป็นต้องมีอาร์กิวเมนต์
คาเลบ

ระวัง grep -f คือ O (N ^ 2) ฉันเชื่อว่า: stackoverflow.com/questions/4780203/ …
rogerdpack

1
diffท่อทำงานขอบคุณรักษา
Felipe Alvarez

เมื่อต้องการบัญชีสำหรับปัญหาการเรียงลำดับคุณสามารถใช้การทดแทนกระบวนการในคำสั่งเพื่อประมวลผลแต่ละไฟล์ก่อนที่grepจำเป็น ตัวอย่าง:grep -F -x -v -f <(sort fileB) <(sort fileA)
Tony Cesaro

@TonyCesaro ที่จะทำงานถ้าชุดข้อมูลของคุณไม่เฉพาะเจาะจงและชุดข้อมูลที่ซ้ำกันไม่จำเป็นต้องนำมาพิจารณา ข้อดีของการใช้งานdiffคือตำแหน่งนั้นในไฟล์จะถูกนำมาพิจารณา
Caleb

57

คำตอบนั้นขึ้นอยู่กับประเภทและรูปแบบของไฟล์ที่คุณเปรียบเทียบ

หากไฟล์ที่คุณกำลังเปรียบเทียบเป็นไฟล์ข้อความที่เรียงลำดับเครื่องมือ GNU ที่เขียนโดย Richard Stallman และ Davide McKenzie ที่เรียกว่าcommอาจทำการกรองที่คุณอยู่ มันเป็นส่วนหนึ่งของ coreutils

ตัวอย่าง

สมมติว่าคุณมี 2 ไฟล์ต่อไปนี้:

$ cat a
1
2
3
4
5

$ cat b
1
2
3
4
5
6

เส้นในไฟล์bที่ไม่ได้อยู่ในไฟล์a:

$ comm <(sort a) <(sort b) -3
    6

1
+1 สำหรับการกล่าวถึงcomm; น่าเสียดายที่commต้องมีไฟล์ที่จัดเรียง
Arcege

11
จัดเรียงพวกเขาเหรอ? comm <(sort a) <(sort b) -1 -2
Sirex

นี่คือรูปแบบแปลก ๆ <()? มันใช้งานได้และฉันได้มันมา แต่มีชื่อแปลก ๆ นี้ไหม?
mlissner

2
@mlissner <()ยังเป็นที่รู้จักกันเป็นกระบวนการทดแทน
มิกุ

1
commถูกเขียนขึ้นครั้งแรกประมาณปี 1973 โดยคนที่ Bell Labs ไม่ใช่ rms คุณหมายถึงการนำ GNU ไปใช้ซึ่งเกิดขึ้นในภายหลัง มีการใช้งานที่แตกต่างกันมากของยูทิลิตี้ Unix ในช่วงหลายปีที่ผ่านมา
Stéphane Chazelas

32

จากstackoverflow ...

comm -23 file1 file2

-23 ไม่แสดงบรรทัดที่อยู่ในไฟล์ทั้งสองหรือเฉพาะในไฟล์ 2 ไฟล์จะต้องมีการเรียงลำดับ (อยู่ในตัวอย่างของคุณ) แต่ถ้าไม่ให้ไพพ์ไปตามการเรียงลำดับแรก ...

ดูหน้าคนที่นี่


นี่ใช้ไม่ได้กับฉันด้วยเหตุผลบางอย่าง ...
ม.ค.

@Jan ไฟล์ของคุณเรียงลำดับ? คุณเรียงลำดับอย่างไร
JJS

8

วิธีการ grep และ comm (มีการเรียงลำดับ) ใช้เวลานานสำหรับไฟล์ขนาดใหญ่ SiegeX และ ghostdog74 แบ่งปันสองวิธี awkที่ยอดเยี่ยมสำหรับการแยกบรรทัดที่ไม่ซ้ำกันของหนึ่งในสองไฟล์บน 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

2
หากคุณกำลังทำสิ่งนี้ด้วยไฟล์ขนาดใหญ่ข้อ จำกัด ของหน่วยความจำในการโหลดไฟล์ขนาดใหญ่ลงในอาเรย์แบบเชื่อมโยงจะเป็นสิ่งต้องห้าม
Charles Duffy

4

หากไฟล์มีขนาดใหญ่และคุณไม่มีคำสั่งซื้อที่กำหนดเองสำหรับรายการของคุณ grep ใช้เวลานานเกินไป ทางเลือกที่รวดเร็วก็คือ

sort file1 > 1 
sort file2 > 2 
diff 1 2 | grep "\>" | sed -e 's/> //'

[file2-file1 ผลไปที่หน้าจอไปป์ที่ไฟล์ ฯลฯ ]

การเปลี่ยน>เป็น<จะได้รับการลบตรงกันข้ามrm 1 2


2

คุณยังสามารถพิจารณา vimdiff มันเน้นความแตกต่างระหว่างไฟล์ในโปรแกรมแก้ไขเป็นกลุ่ม


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