Mam dwa pliki. Podejrzewam, że jeden plik jest podzbiorem drugiego. Czy istnieje sposób na różnicowanie plików, aby zidentyfikować (w zwięzły sposób), gdzie w pierwszym pliku mieści się drugi plik?
Czy masz na myśli, że linie jednego pliku są podciągiem drugiego, a właściwie ciągłym ciągiem znaków?
Kaz
Ciągły podciąg, @Kaz.
Richard
Odpowiedzi:
14
diff -e bigger smaller zrobi lewę, ale wymaga pewnej interpretacji, ponieważ wynikiem jest „prawidłowy skrypt ed”.
Zrobiłem dwa pliki, „większy” i „mniejszy”, w których zawartość „mniejszego” jest identyczna z liniami od 5 do 9 „większego” robiącego „diff -e większy mniejszy” dostałem:
% diff -e bigger smaller
10,15d
1,4d
Co oznacza „usuń wiersze od 10 do 15 z„ większych ”, a następnie usuń wiersze od 1 do 4, aby uzyskać„ mniejsze ”. Oznacza to, że „mniejsze” to wiersze od 5 do 9 „większego”.
Odwracanie nazw plików sprawiło mi coś bardziej skomplikowanego. Jeśli „mniejsze” naprawdę stanowi podzbiór „większych”, na wyjściu pojawią się tylko polecenia „d” (do usunięcia).
Możesz to zrobić wizualnie za pomocą meld . Niestety jest to narzędzie GUI, ale jeśli chcesz to zrobić tylko raz i na stosunkowo małym pliku, powinno być dobrze:
Poniższy obraz przedstawia dane wyjściowe meld a b:
Co ma 777zrobić? Rozumiem, że podajesz NULL, $/ale dlaczego? Ponieważ są to raczej ezoteryczne przełączniki, wyjaśnienie byłoby miłe dla osób nie będących w Perlu.
terdon
1
@terdon Naprawdę robię to, aby zatamować pliki w całości. Dodano wyjaśnienie.
Joseph R.
Ale dlaczego to konieczne? $a=<$fh>w każdym razie powinien to być slurp, prawda?
terdon
1
@terdon Nie wiem, nie. Domyślnie $/jest ustawione na \ntak, aby $a=<$fh>można było odczytać tylko jedną linię pliku $fh. Chyba perlże zachowanie wiersza polecenia ma oczywiście inne ustawienia domyślne, których nie jestem świadomy?
Joseph R.
Argh, tak, moje złe, prawie nigdy nie robię plików i nie używam tego while $foo=<FILE>idiomu, więc nie byłem pewien i przeprowadziłem (zły) test, który wydawał się działać. Nieważne :).
terdon
1
Jeśli pliki są plikami tekstowymi, a smallerwewnątrz biggerzaczyna się na początku wiersza, nie jest to zbyt trudne do wdrożenia za pomocą awk:
Twoje pytanie brzmi „Zróżnicowana głowa plików”. Jeśli naprawdę masz na myśli, że jeden plik jest głową drugiego, to prosty cmppowie ci, że:
cmp big_file small_file
cmp: EOF on small_file
Oznacza to, że różnica między tymi dwoma plikami nie została wykryta do momentu osiągnięcia końca pliku podczas odczytu small_file.
Jeśli jednak masz na myśli, że cały tekst małego pliku może wystąpić w dowolnym miejscu w środku big_file, zakładając, że możesz zmieścić oba pliki w pamięci, możesz użyć
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;
'
Spowoduje to wydrukowanie przesunięcia w obrębie, w big_filektórym znajduje się zawartość small_file(np. 0, jeśli small_filepasuje na początku big_file). Jeśli small_filenie pasuje do środka big_file, nic nie zostanie wydrukowane. W przypadku błędu status wyjścia będzie różny od zera.
Odpowiedzi:
diff -e bigger smaller
zrobi lewę, ale wymaga pewnej interpretacji, ponieważ wynikiem jest „prawidłowy skrypt ed”.Zrobiłem dwa pliki, „większy” i „mniejszy”, w których zawartość „mniejszego” jest identyczna z liniami od 5 do 9 „większego” robiącego „diff -e większy mniejszy” dostałem:
Co oznacza „usuń wiersze od 10 do 15 z„ większych ”, a następnie usuń wiersze od 1 do 4, aby uzyskać„ mniejsze ”. Oznacza to, że „mniejsze” to wiersze od 5 do 9 „większego”.
Odwracanie nazw plików sprawiło mi coś bardziej skomplikowanego. Jeśli „mniejsze” naprawdę stanowi podzbiór „większych”, na wyjściu pojawią się tylko polecenia „d” (do usunięcia).
źródło
Możesz to zrobić wizualnie za pomocą meld . Niestety jest to narzędzie GUI, ale jeśli chcesz to zrobić tylko raz i na stosunkowo małym pliku, powinno być dobrze:
Poniższy obraz przedstawia dane wyjściowe
meld a b
:źródło
vimdiff
, co jest dostępne w terminalu.Jeśli pliki są wystarczająco małe, możesz przelać je oba do Perla i poprosić jego silnik wyrażenia regularnego:
-0777
Przełącznik przesyła zlecenie Perl aby ustawić jej separator rekordu wejściowego$/
do wartości nieokreślonej, tak aby pliki SLURP końca.źródło
777
zrobić? Rozumiem, że podajesz NULL,$/
ale dlaczego? Ponieważ są to raczej ezoteryczne przełączniki, wyjaśnienie byłoby miłe dla osób nie będących w Perlu.$a=<$fh>
w każdym razie powinien to być slurp, prawda?$/
jest ustawione na\n
tak, aby$a=<$fh>
można było odczytać tylko jedną linię pliku$fh
. Chybaperl
że zachowanie wiersza polecenia ma oczywiście inne ustawienia domyślne, których nie jestem świadomy?while $foo=<FILE>
idiomu, więc nie byłem pewien i przeprowadziłem (zły) test, który wydawał się działać. Nieważne :).Jeśli pliki są plikami tekstowymi, a
smaller
wewnątrzbigger
zaczyna się na początku wiersza, nie jest to zbyt trudne do wdrożenia za pomocąawk
:źródło
Twoje pytanie brzmi „Zróżnicowana głowa plików”. Jeśli naprawdę masz na myśli, że jeden plik jest głową drugiego, to prosty
cmp
powie ci, że:Oznacza to, że różnica między tymi dwoma plikami nie została wykryta do momentu osiągnięcia końca pliku podczas odczytu
small_file
.Jeśli jednak masz na myśli, że cały tekst małego pliku może wystąpić w dowolnym miejscu w środku
big_file
, zakładając, że możesz zmieścić oba pliki w pamięci, możesz użyćSpowoduje to wydrukowanie przesunięcia w obrębie, w
big_file
którym znajduje się zawartośćsmall_file
(np. 0, jeślismall_file
pasuje na początkubig_file
). Jeślismall_file
nie pasuje do środkabig_file
, nic nie zostanie wydrukowane. W przypadku błędu status wyjścia będzie różny od zera.źródło