ส่วนหัวของไฟล์ต่าง


11

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


ที่เกี่ยวข้อง: unix.stackexchange.com/questions/79135/…
slm

คุณหมายถึงบรรทัดของไฟล์หนึ่งเรียงตามลำดับของไฟล์อื่นหรือเป็นสตริงย่อยที่ต่อเนื่องกันหรือไม่?
Kaz

สตริงย่อยที่ต่อเนื่องกัน @Kaz
ริชาร์ด

คำตอบ:


14

diff -e bigger smaller จะทำการหลอกลวง แต่ต้องการการตีความบางอย่างเนื่องจากผลลัพธ์คือ "สคริปต์ ed ที่ถูกต้อง"

ฉันสร้างไฟล์สองไฟล์คือ "ใหญ่กว่า" และ "เล็กกว่า" ซึ่งเนื้อหาของ "เล็กกว่า" นั้นเหมือนกับบรรทัดที่ 5 ถึง 9 ของ "ใหญ่กว่า" ในการทำ `diff -e ใหญ่กว่า" ฉัน:

% diff -e bigger smaller
10,15d
1,4d

ซึ่งหมายความว่า "ลบบรรทัด 10 ถึง 15 ของ 'ใหญ่กว่า' จากนั้นลบบรรทัด 1 ถึง 4 เพื่อรับ 'เล็กกว่า'" นั่นหมายความว่า "เล็กกว่า" คือบรรทัด 5 ถึง 9 ของ "ใหญ่กว่า"

การย้อนกลับชื่อไฟล์ทำให้ฉันมีความซับซ้อนมากขึ้น หาก "เล็กลง" ถือเป็นส่วนย่อยของ "ใหญ่กว่า" อย่างแท้จริงคำสั่ง 'd' (สำหรับลบ) เท่านั้นที่จะปรากฏในเอาต์พุต


5

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

ภาพด้านล่างเป็นผลลัพธ์ของmeld a b:

ป้อนคำอธิบายรูปภาพที่นี่


1
Meld เป็นคนดี แต่มันเล่นได้ไม่ดีกับไฟล์ 100MB +
ริชาร์ด

@ ไม่สนใจมันไม่ได้และฉันต้องการเครื่องมือบรรทัดคำสั่งต่อไปฉันแค่คิดว่าฉันพูดถึงมัน
terdon

ดูเหมือนว่ามากvimdiffซึ่งมีอยู่ในสถานี
Patrick

2

หากไฟล์มีขนาดเล็กพอคุณสามารถแยกไฟล์ทั้งสองเป็น Perl และให้เอนจิ้น regex ทำการหลอกลวง:

perl -0777e '
        open "$FILE1","<","file_1";
        open "$FILE2","<","file_2";
        $file_1 = <$FILE1>;
        $file_2 = <$FILE2>;
        print "file_2 is", $file_1 =~ /\Q$file_2\E/ ? "" : "not";
        print " a subset of file_1\n";
'

-0777สวิตช์สั่ง Perl เพื่อตั้งค่าการบันทึกการป้อนข้อมูลของคั่น$/กับค่าไม่ได้กำหนดเพื่อให้เป็นไปไฟล์ Slurp สมบูรณ์


1
อะไร777ทำอย่างไร ฉันคิดว่าคุณผ่าน NULL ไปแล้ว$/แต่ทำไม? นอกจากนี้เนื่องจากสิ่งเหล่านี้เป็นสวิตช์ความลับแบบ kinda คำอธิบายจะดีสำหรับคนที่ไม่ได้เป็น Perl
terdon

1
@terdon จริง ๆ แล้วฉันทำเพื่อ slurp ไฟล์ทั้งหมด เพิ่มคำอธิบายแล้ว
โจเซฟอาร์

แต่ทำไมถึงจำเป็น? $a=<$fh>ควร slurp ต่อไปใช่มั้ย
terdon

1
@terdon ไม่ทราบว่าฉันไม่ โดยค่าเริ่มต้น$/ถูกตั้งค่าเป็น\nดังนั้นที่$a=<$fh>จะอ่านเพียงหนึ่งบรรทัดของไฟล์ที่$fhได้รับการเปิด perlพฤติกรรมของบรรทัดคำสั่งแน่นอนว่ามีค่าเริ่มต้นที่ฉันไม่รู้
โจเซฟอาร์

ใช่ฉันไม่ดีฉันแทบจะไม่เคยใช้ไฟล์while $foo=<FILE>สำนวนหรือใช้สำนวนดังนั้นฉันจึงไม่แน่ใจและทำการทดสอบ (ผิด) ซึ่งดูเหมือนจะใช้งานได้ ไม่เป็นไร :).
terdon

1

หากไฟล์เป็นไฟล์ข้อความและsmallerภายในbiggerเริ่มต้นที่จุดเริ่มต้นของบรรทัดก็ไม่ยากที่จะนำไปใช้กับawk:

awk -v i=0 'NR==FNR{l[n++]=$0;next}
    {if ($0 == l[i]) {if (++i == n) {print FNR-n+1;exit}} else i=0}
    ' smaller bigger

1

คำถามของคุณคือ "Diff head of files" หากคุณหมายถึงว่าไฟล์หนึ่งเป็นส่วนหัวของอีกไฟล์หนึ่งไฟล์ธรรมดาcmpจะบอกคุณว่า:

cmp big_file small_file
cmp: EOF on small_file

small_fileที่จะบอกคุณว่าความแตกต่างระหว่างทั้งสองไฟล์ไม่พบจนกว่าจะสิ้นสุดของแฟ้มก็มาถึงในขณะที่อ่าน

หากคุณหมายถึงว่าข้อความทั้งหมดของไฟล์ขนาดเล็กสามารถเกิดขึ้นได้ทุกที่ภายในbig_fileสมมติว่าคุณสามารถใส่ไฟล์ทั้งสองในหน่วยความจำคุณสามารถใช้

perl -le '
   use autodie;
   undef $/;
   open SMALL, "<", "small_file";
   open BIG, "<", "big_file";
   $small = <SMALL>;
   $big = <BIG>;
   $pos = index $big, $small;
   print $pos if $pos >= 0;
'

สิ่งนี้จะพิมพ์ออฟเซ็ตภายในbig_fileที่เนื้อหาของsmall_fileอยู่ (เช่น 0 ถ้าsmall_fileตรงกับตอนต้นของbig_file) หากsmall_fileไม่ตรงกับภายในbig_fileจะไม่มีการพิมพ์อะไรเลย หากมีข้อผิดพลาดสถานะการออกจะไม่ใช่ศูนย์

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