Diff глава файлов


11

У меня есть два файла. Я подозреваю, что один файл является подмножеством другого. Есть ли способ различать файлы, чтобы определить (кратким образом), куда в первом файле помещается второй файл?



Вы имеете в виду, что строки одного файла являются подпоследовательностью другого или на самом деле смежной подстрокой?
Каз

Непрерывная подстрока, @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 . К сожалению, это инструмент с графическим интерфейсом, но если вы просто хотите сделать это один раз и для относительно небольшого файла, все будет хорошо:

Изображение ниже является выводом meld a b:

введите описание изображения здесь


1
Мелд хорош, но он не играет так же хорошо с файлами размером более 100 МБ.
Ричард

@Richard нет, это не так, и я все равно предпочел бы инструмент командной строки, я просто подумал, что упомяну это.
Terdon

Очень похоже на то vimdiff, что доступно в терминале.
Патрик

2

Если файлы достаточно малы, вы можете перетянуть их в Perl и сделать так, чтобы механизм их регулярных выражений сделал свое дело:

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 , чтобы установить свой входной разделитель записей $/в неопределенное значение так, чтобы хлебать файлы полностью.


1
Что делает 777? Я так понимаю, вы передаете NULL, $/но почему? Также, поскольку это своего рода эзотерические переключатели, объяснение было бы неплохо для людей, не относящихся к Perl.
Terdon

1
@terdon Я действительно делаю это, чтобы хлебать файлы целиком. Объяснение добавлено.
Джозеф Р.

Но зачем это нужно? $a=<$fh>должно все равно хлебать, верно?
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

Ваш вопрос "Диффер глава файлов". Если вы действительно имеете в виду, что один файл является главой другого, то простой 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, то ничего не будет напечатано. Если есть ошибка, статус выхода будет ненулевым.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.