У меня есть два файла. Я подозреваю, что один файл является подмножеством другого. Есть ли способ различать файлы, чтобы определить (кратким образом), куда в первом файле помещается второй файл?
Вы имеете в виду, что строки одного файла являются подпоследовательностью другого или на самом деле смежной подстрокой?
Каз
Непрерывная подстрока, @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» (для удаления).
Вы можете сделать это визуально с Meld . К сожалению, это инструмент с графическим интерфейсом, но если вы просто хотите сделать это один раз и для относительно небольшого файла, все будет хорошо:
Мелд хорош, но он не играет так же хорошо с файлами размером более 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 , чтобы установить свой входной разделитель записей $/в неопределенное значение так, чтобы хлебать файлы полностью.
Что делает 777? Я так понимаю, вы передаете NULL, $/но почему? Также, поскольку это своего рода эзотерические переключатели, объяснение было бы неплохо для людей, не относящихся к Perl.
Terdon
1
@terdon Я действительно делаю это, чтобы хлебать файлы целиком. Объяснение добавлено.
Джозеф Р.
Но зачем это нужно? $a=<$fh>должно все равно хлебать, верно?
Terdon
1
@terdon Не то, что я знаю, нет. По умолчанию $/установлено значение \nтак, что $a=<$fh>при чтении $fhбыла открыта только одна строка файла . Если, конечно, perlповедение командной строки не имеет других значений по умолчанию, о которых я не знаю?
Джозеф Р.
Ага, да, мой плохой, я почти никогда не слежу за файлами и не использую while $foo=<FILE>идиомы, поэтому я не был уверен и провел (неправильный) тест, который, похоже, сработал. Ничего :).
Terdon
1
Если файлы представляют собой текстовые файлы и smaller, biggerначиная с начала в начале строки, это не так сложно реализовать с помощью awk:
Ваш вопрос "Диффер глава файлов". Если вы действительно имеете в виду, что один файл является главой другого, то простой 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, то ничего не будет напечатано. Если есть ошибка, статус выхода будет ненулевым.
Ответы:
diff -e bigger smaller
сделает свое дело, но требует некоторой интерпретации, поскольку на выходе получается «действительный сценарий ed».Я сделал два файла, «больше» и «меньше», где содержимое «поменьше» идентично строкам с 5 по 9 «больше», выполнив «diff -e большее поменьше»:
Что означает «удалить строки с 10 по 15« больше », а затем удалить строки с 1 по 4, чтобы получить« меньше »». Это означает, что «меньше» - это строки с 5 по 9 «больше».
Изменение имен файлов сделало меня чем-то более сложным. Если «поменьше» действительно составляет подмножество «побольше», то в выводе будут отображаться только команды «d» (для удаления).
источник
Вы можете сделать это визуально с Meld . К сожалению, это инструмент с графическим интерфейсом, но если вы просто хотите сделать это один раз и для относительно небольшого файла, все будет хорошо:
Изображение ниже является выводом
meld a b
:источник
vimdiff
, что доступно в терминале.Если файлы достаточно малы, вы можете перетянуть их в Perl и сделать так, чтобы механизм их регулярных выражений сделал свое дело:
-0777
Переключатель инструктирует Perl , чтобы установить свой входной разделитель записей$/
в неопределенное значение так, чтобы хлебать файлы полностью.источник
777
? Я так понимаю, вы передаете NULL,$/
но почему? Также, поскольку это своего рода эзотерические переключатели, объяснение было бы неплохо для людей, не относящихся к Perl.$a=<$fh>
должно все равно хлебать, верно?$/
установлено значение\n
так, что$a=<$fh>
при чтении$fh
была открыта только одна строка файла . Если, конечно,perl
поведение командной строки не имеет других значений по умолчанию, о которых я не знаю?while $foo=<FILE>
идиомы, поэтому я не был уверен и провел (неправильный) тест, который, похоже, сработал. Ничего :).Если файлы представляют собой текстовые файлы и
smaller
,bigger
начиная с начала в начале строки, это не так сложно реализовать с помощьюawk
:источник
Ваш вопрос "Диффер глава файлов". Если вы действительно имеете в виду, что один файл является главой другого, то простой
cmp
скажет вам, что:Это говорит о том, что разница между этими двумя файлами не была обнаружена, пока не был достигнут конец файла во время чтения
small_file
.Однако, если вы имеете в виду, что весь текст небольшого файла может находиться где угодно внутри
big_file
, то при условии, что вы можете разместить оба файла в памяти, вы можете использоватьЭто напечатает смещение в пределах того,
big_file
где находится содержимоеsmall_file
(например, 0, еслиsmall_file
совпадает в началеbig_file
). Еслиsmall_file
не совпадает внутриbig_file
, то ничего не будет напечатано. Если есть ошибка, статус выхода будет ненулевым.источник