У мене два файли. Підозрюю, що один файл є підмножиною іншого. Чи є спосіб розрізнити файли, щоб визначити (стислим чином), де в першому файлі підходить другий файл?
У мене два файли. Підозрюю, що один файл є підмножиною іншого. Чи є спосіб розрізнити файли, щоб визначити (стислим чином), де в першому файлі підходить другий файл?
Відповіді:
diff -e bigger smaller
зробить трюк, але вимагає певної інтерпретації, оскільки вихід - це "дійсний сценарій редагування".
Я зробив два файли, "більший" і "менший", де вміст "менший" ідентичний рядкам 5 - 9 "більший", що робить `diff -e більший менший", отримав мене:
% diff -e bigger smaller
10,15d
1,4d
Що означає "видалити рядки з 10 по 15 з" більшої ", а потім видалити рядки з 1 по 4, щоб отримати" менший "". Це означає, що "менший" - це рядки від 5 до 9 "більшої".
Зміна імен файлів отримала мені щось складніше. Якщо "менший" справді становить підмножину "більших", у висновку відображаються лише команди "d" (для видалення).
Зробити це можна візуально за допомогою монтажу . На жаль, це інструмент графічного інтерфейсу, але якщо ви просто хочете це зробити один раз, і на відносно невеликому файлі, це повинно бути добре:
Зображення нижче - це результат meld a b
:
vimdiff
, що доступно в терміналі.
Якщо файлів достатньо мало, ви можете прив’язати їх як до 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 , щоб встановити свій вхідний роздільник записів $/
в невизначене значення так, щоб сьорбати файли повністю.
777
? Я вважаю, ти передаєш NULL як, $/
але чому? Крім того, що це своєрідні езотеричні перемикачі, пояснення було б непоганим для людей, які не мають перлів.
$a=<$fh>
чи варто сіпатися все-таки так?
$/
встановлено \n
так, що $a=<$fh>
було $fh
б відкрито лише один рядок файлу . Якщо, звичайно, perl
поведінка командного рядка не має різних за замовчуванням, про які я не знаю?
while $foo=<FILE>
ідіому, тому я не був впевнений і провів (неправильний) тест, який, здавалося, спрацював. Не звертай уваги :).
Якщо файли - це текстові файли, і 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
Ваше запитання - "Різна заголовок файлів". Якщо ви дійсно маєте на увазі, що один файл є головою іншого, то простий 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
, то нічого не буде надруковано. Якщо є помилка, статус виходу буде не нульовим.