Kepala file berbeda

11

Saya punya dua file. Satu file, saya kira, adalah bagian dari yang lain. Apakah ada cara untuk membedakan file-file untuk mengidentifikasi (secara ringkas) di mana pada file pertama file kedua cocok?

Richard
sumber
Apakah maksud Anda baris dari satu file adalah yang berikutnya, atau sebenarnya substring yang berdekatan?
Kaz
Substring yang berdekatan, @Kaz.
Richard

Jawaban:

14

diff -e bigger smaller akan melakukan trik, tetapi memerlukan beberapa interpretasi, karena hasilnya adalah "skrip ed yang valid".

Saya membuat dua file, "lebih besar" dan "lebih kecil", di mana isi "lebih kecil" identik dengan baris 5 hingga 9 dari "lebih besar" yang melakukan `beda-lebih besar lebih kecil" membuat saya:

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

Yang berarti "hapus baris 10 hingga 15 dari 'lebih besar', dan kemudian hapus baris 1 hingga 4, untuk mendapatkan 'lebih kecil'". Itu berarti "lebih kecil" adalah garis 5 sampai 9 dengan "lebih besar".

Membalikkan nama file memberi saya sesuatu yang lebih rumit. Jika "lebih kecil" benar-benar merupakan subset dari "lebih besar", hanya perintah 'd' (untuk dihapus) yang akan muncul di output.

Bruce Ediger
sumber
5

Anda dapat melakukan ini secara visual dengan berbaur . Sayangnya, ini adalah alat GUI tetapi jika Anda hanya ingin melakukan ini sekali saja, dan pada file yang relatif kecil, itu akan baik-baik saja:

Gambar di bawah ini adalah output dari meld a b:

masukkan deskripsi gambar di sini

terdon
sumber
1
Meld bagus, tetapi tidak bisa dimainkan dengan baik dengan 100MB + file.
Richard
@Richard tidak tidak dan saya lebih suka alat baris perintah, saya hanya berpikir saya akan menyebutkannya.
terdon
Tampak sangat mirip vimdiff, yang tersedia di terminal.
Patrick
2

Jika file-file tersebut cukup kecil, Anda dapat menyerupkan keduanya ke Perl dan minta mesin regex-nya melakukan trik:

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";
'

The -0777beralih menginstruksikan Perl untuk mengatur pemisah record input $/dengan nilai terdefinisi sehingga file slurp sepenuhnya.

Joseph R.
sumber
1
Apa yang 777harus dilakukan Saya menganggap Anda melewati NULL $/tetapi mengapa? Juga karena ini adalah saklar yang agak esoteris, penjelasan akan lebih baik untuk orang-orang non-perl.
terdon
1
@terdon saya memang melakukannya untuk menyeruput seluruh file. Penjelasan ditambahkan.
Joseph R.
Tetapi mengapa itu perlu? $a=<$fh>haruskah menyeruputnya kan?
terdon
1
@terdon Bukan yang saya tahu, tidak. Secara default $/diatur ke \nsehingga $a=<$fh>akan membaca hanya satu baris file $fhtelah dibuka. Kecuali perlperilaku baris perintah tentu saja memiliki standar yang berbeda yang saya tidak sadari?
Joseph R.
Argh, ya, salah saya, saya hampir tidak pernah menyeruput file atau menggunakan while $foo=<FILE>idiom jadi saya tidak yakin dan menjalankan tes (salah) yang tampaknya berhasil. Sudahlah :).
terdon
1

Jika file adalah file teks dan smaller, dalam biggermulai di awal baris, itu tidak terlalu sulit untuk diterapkan dengan 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
Stéphane Chazelas
sumber
1

Pertanyaan Anda adalah "Diff head of files". Jika Anda benar-benar bermaksud bahwa satu file adalah kepala dari yang lain, maka yang sederhana cmpakan memberi tahu Anda bahwa:

cmp big_file small_file
cmp: EOF on small_file

Itu memberi tahu Anda bahwa perbedaan antara dua file tidak terdeteksi sampai akhir file tercapai saat membaca small_file.

Namun, jika Anda maksudkan bahwa seluruh teks file kecil dapat terjadi di mana saja di dalam big_file, maka dengan asumsi Anda dapat memuat kedua file dalam memori, Anda dapat menggunakan

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;
'

Ini akan mencetak offset di big_filemana konten small_fileberada (mis. 0 jika small_filecocok di awal big_file). Jika small_filetidak cocok di dalam big_file, maka tidak ada yang akan dicetak. Jika ada kesalahan, status keluar akan menjadi nol.

jrw32982 mendukung Monica
sumber