วิธีการเปรียบเทียบสองไฟล์ที่แตกต่างกันทีละบรรทัดในยูนิกซ์?


13

file1:

123
234
345
456

file2:

123
234
343
758

ผลลัพธ์ที่คาดหวัง: File3:

TRUE
TRUE
FALSE
FALSE

ดังนั้นรหัสควรเปรียบเทียบสองไฟล์และพิมพ์ 'TRUE' หากตรงกันมิฉะนั้นควรพิมพ์ 'FALSE' ในไฟล์ใหม่ ใครช่วยกรุณาแก้ปัญหาสำหรับเรื่องนี้?


10
จะเกิดอะไรขึ้นถ้าไฟล์ทั้งสองมีความยาวไม่เท่ากัน? คุณมีปัญหาในการแก้ไขปัญหาส่วนใด
Kusalananda

9
diffคุณอาจต้องการที่จะดูที่
Panki

2
คำสั่งที่มีประโยชน์อื่น ๆ commในสถานการณ์เหล่านี้คือ มันทำให้ง่ายต่อการแสดงรายการบรรทัดที่ทั้งสองไฟล์มีร่วมกันหรือไม่ซ้ำกันกับคนอื่น
Giacomo Alzetta

1
@GiacomoAlzetta สิ่งที่มีcommคือมันต้องมีการป้อนข้อมูลที่เรียง นอกเหนือจากความจริงที่ว่าตัวอย่างเช่นในคำถามไม่ได้มีการป้อนข้อมูลที่เรียงลำดับคำถามที่ไม่เคยอ้างว่านี่เป็นข้อมูลจริงที่มีการใช้และไม่เคยพูดอะไรเกี่ยวกับการสั่งซื้อของข้อมูล
Kusalananda

2
nlเคล็ดลับของαғsнιη มีประโยชน์commสำหรับการจัดเรียงไฟล์ในไฟล์
เกล็นแจ็คแมน

คำตอบ:


56

ใช้diffคำสั่งดังต่อไปนี้ในbashหรือเชลล์อื่น ๆ ที่รองรับ<(...) การทดแทนกระบวนการหรือคุณสามารถเลียนแบบมันดังแสดงที่นี่ :

diff --new-line-format='FALSE'$'\n' \
     --old-line-format='' \
     --unchanged-line-format='TRUE'$'\n' \
<(nl file1) <(nl file2)

ผลผลิตจะเป็น:

TRUE
TRUE
FALSE
FALSE

--new-line-format='FALSE'$'\nพิมพ์FALSEถ้าบรรทัดแตกต่างกันและเมื่อ--old-line-format=''เราปิดการใช้งานเอาต์พุตหากบรรทัดแตกต่างกันสำหรับ file1 ซึ่งเรียกว่าไฟล์เก่าเป็นคำสั่ง diff (เราสามารถสลับสิ่งเหล่านี้ได้เช่นกันหมายความว่าหนึ่งในนั้นควรพิมพ์FALSEอีกอันควรปิดใช้งาน)

--unchanged-line-format='TRUE'$'\n'พิมพ์TRUEถ้าบรรทัดเหมือนกัน $'\n'ไวยากรณ์แบบ C หลบหนีจะใช้ในการพิมพ์บรรทัดใหม่หลังจากที่การส่งออกแต่ละบรรทัด


24

สมมติว่าไฟล์ไม่มีตัวอักษรแท็บ:

$ paste file1 file2 | awk -F '\t' '{ print ($1 == $2 ? "TRUE" : "FALSE") }'
TRUE
TRUE
FALSE
FALSE

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


10

สมมติว่าไฟล์ทั้งสองมีจำนวนบรรทัดเท่ากัน:

awk '{getline f2 < "file2"; print f2 == $0 ? "TRUE" : "FALSE"}' file1

นั่นคือการเปรียบเทียบตัวเลขถ้าสตริงที่จะเปรียบเทียบเป็นตัวเลขและคำศัพท์เป็นอย่างอื่น เช่น100และ1.0e2จะถือว่าเหมือนกัน เปลี่ยนเป็นf2"" == $0บังคับให้มีการเปรียบเทียบคำศัพท์ในทุกกรณี

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


7

Python 3

with open('file1') as file1, open('file2') as file2:
    for line1, line2 in zip(file1, file2):
        print(line1 == line2)

เอาท์พุท:

True
True
False
False

หากคุณต้องการTRUEและเป็นFALSEตัวพิมพ์ใหญ่ให้แทนที่สายการพิมพ์ด้วยหนึ่งในสิ่งเหล่านี้:

print(str(line1 == line2).upper())
print('TRUE' if line1 == line2 else 'FALSE')

2
ในหลาม 2 ทำimport itertoolsครั้งแรกและจากนั้นใช้แทนitertools.izip zipมิฉะนั้นจะอ่านไฟล์ทั้งสองไปยังหน่วยความจำอาจใช้หน่วยความจำมากเกินไป
pts

4

ในbashการอ่านจากแต่ละไฟล์ในwhileลูปเปรียบเทียบบรรทัดการอ่านและการพิมพ์TRUEหรือFALSEเหมาะสม:

while IFS= read -r -u3 line1; IFS= read -r -u4 line2; do
    [[ $line1 == $line2 ]] && echo TRUE || echo FALSE
done 3<file1 4<file2

การเรียกสองครั้งเพื่อreadอ่านจากตัวอธิบายไฟล์ 3 และ 4 ตามลำดับ ไฟล์จะถูกเปลี่ยนเส้นทางไปยังสิ่งเหล่านี้โดยมีการเปลี่ยนเส้นทางอินพุตสองครั้งในลูป


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