Ich habe zwei Dateien. Ich vermute, eine Datei ist eine Teilmenge der anderen. Gibt es eine Möglichkeit, die Dateien zu unterscheiden, um (auf prägnante Weise) zu identifizieren, wo in die erste Datei die zweite Datei passt?
Meinen Sie damit, dass die Zeilen einer Datei eine Teilsequenz der anderen oder tatsächlich eine zusammenhängende Teilzeichenfolge sind?
Kaz
Ein zusammenhängender Teilstring, @Kaz.
Richard
Antworten:
14
diff -e bigger smaller wird den Trick machen, erfordert aber einige Interpretation, da die Ausgabe ein "gültiges ed-Skript" ist.
Ich habe zwei Dateien erstellt, "größer" und "kleiner", wobei der Inhalt von "kleiner" mit den Zeilen 5 bis 9 von "größer" identisch ist, wobei "diff -e größer kleiner" mich dazu gebracht hat:
% diff -e bigger smaller
10,15d
1,4d
Dies bedeutet "Löschen Sie die Zeilen 10 bis 15 von" größer "und dann die Zeilen 1 bis 4, um" kleiner "zu werden". Das heißt, "kleiner" sind die Zeilen 5 bis 9 von "größer".
Das Umkehren der Dateinamen hat mich etwas komplizierter gemacht. Wenn "kleiner" wirklich eine Teilmenge von "größer" darstellt, werden in der Ausgabe nur "d" -Befehle (zum Löschen) angezeigt.
Sie können dies visuell mit meld tun . Leider ist es ein GUI-Tool, aber wenn Sie dies nur einmal und in einer relativ kleinen Datei tun möchten, sollte es in Ordnung sein:
Was macht 777das Ich nehme an, Sie übergeben NULL, $/aber warum? Auch da dies irgendwie esoterische Schalter sind, wäre eine Erklärung für die Nicht-Perl-Leute nett.
Terdon
1
@terdon Ich mache es in der Tat, um die Dateien als Ganzes zu schlürfen. Erklärung hinzugefügt.
Joseph R.
Aber warum ist das notwendig? $a=<$fh>sollte sowieso schlürfen oder?
Terdon
1
@terdon Nicht das ich wüsste, nein. Standardmäßig $/ist so eingestellt, \ndass $a=<$fh>nur eine Zeile der Datei gelesen wird, für die $fhgeöffnet wurde. Es sei denn natürlich perl, das Befehlszeilenverhalten hat andere Standardeinstellungen, die mir nicht bekannt sind.
Joseph R.
Argh, ja, mein schlechtes, ich schlürfe fast nie Dateien oder benutze die while $foo=<FILE>Redewendung, also war ich mir nicht sicher und führte einen (falschen) Test durch, der zu funktionieren schien. Keine Ursache :).
Terdon
1
Wenn es sich bei den Dateien um Textdateien handelt und smallerinnerhalb von biggeram Anfang einer Zeile beginnt, ist die Implementierung nicht allzu schwierig mit awk:
Ihre Frage lautet "Diff head of files". Wenn Sie wirklich meinen, dass eine Datei der Kopf der anderen ist, dann cmpsagt Ihnen eine einfache Datei Folgendes:
cmp big_file small_file
cmp: EOF on small_file
Dies zeigt Ihnen, dass ein Unterschied zwischen den beiden Dateien erst erkannt wurde, als beim Lesen das Dateiende erreicht wurde small_file.
Wenn Sie jedoch meinen, dass der gesamte Text einer kleinen Datei irgendwo im Inneren vorkommen kann big_file, können Sie verwenden, vorausgesetzt, Sie können beide Dateien in den Speicher einpassen
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;
'
Dadurch wird der Versatz gedruckt, in big_filedem sich der Inhalt von small_filebefindet (z. B. 0, wenn er small_filezu Beginn übereinstimmt big_file). Wenn small_filees innen nicht übereinstimmt big_file, wird nichts gedruckt. Wenn ein Fehler auftritt, ist der Exit-Status ungleich Null.
Antworten:
diff -e bigger smaller
wird den Trick machen, erfordert aber einige Interpretation, da die Ausgabe ein "gültiges ed-Skript" ist.Ich habe zwei Dateien erstellt, "größer" und "kleiner", wobei der Inhalt von "kleiner" mit den Zeilen 5 bis 9 von "größer" identisch ist, wobei "diff -e größer kleiner" mich dazu gebracht hat:
Dies bedeutet "Löschen Sie die Zeilen 10 bis 15 von" größer "und dann die Zeilen 1 bis 4, um" kleiner "zu werden". Das heißt, "kleiner" sind die Zeilen 5 bis 9 von "größer".
Das Umkehren der Dateinamen hat mich etwas komplizierter gemacht. Wenn "kleiner" wirklich eine Teilmenge von "größer" darstellt, werden in der Ausgabe nur "d" -Befehle (zum Löschen) angezeigt.
quelle
Sie können dies visuell mit meld tun . Leider ist es ein GUI-Tool, aber wenn Sie dies nur einmal und in einer relativ kleinen Datei tun möchten, sollte es in Ordnung sein:
Das Bild unten ist die Ausgabe von
meld a b
:quelle
vimdiff
, was im Terminal verfügbar ist.Wenn die Dateien klein genug sind, können Sie beide in Perl schlürfen und die Regex-Engine den Trick ausführen lassen:
Der
-0777
Switch weist Perl an, das Trennzeichen$/
für Eingabedatensätze auf den undefinierten Wert zu setzen, um Dateien vollständig zu verschlingen.quelle
777
das Ich nehme an, Sie übergeben NULL,$/
aber warum? Auch da dies irgendwie esoterische Schalter sind, wäre eine Erklärung für die Nicht-Perl-Leute nett.$a=<$fh>
sollte sowieso schlürfen oder?$/
ist so eingestellt,\n
dass$a=<$fh>
nur eine Zeile der Datei gelesen wird, für die$fh
geöffnet wurde. Es sei denn natürlichperl
, das Befehlszeilenverhalten hat andere Standardeinstellungen, die mir nicht bekannt sind.while $foo=<FILE>
Redewendung, also war ich mir nicht sicher und führte einen (falschen) Test durch, der zu funktionieren schien. Keine Ursache :).Wenn es sich bei den Dateien um Textdateien handelt und
smaller
innerhalb vonbigger
am Anfang einer Zeile beginnt, ist die Implementierung nicht allzu schwierig mitawk
:quelle
Ihre Frage lautet "Diff head of files". Wenn Sie wirklich meinen, dass eine Datei der Kopf der anderen ist, dann
cmp
sagt Ihnen eine einfache Datei Folgendes:Dies zeigt Ihnen, dass ein Unterschied zwischen den beiden Dateien erst erkannt wurde, als beim Lesen das Dateiende erreicht wurde
small_file
.Wenn Sie jedoch meinen, dass der gesamte Text einer kleinen Datei irgendwo im Inneren vorkommen kann
big_file
, können Sie verwenden, vorausgesetzt, Sie können beide Dateien in den Speicher einpassenDadurch wird der Versatz gedruckt, in
big_file
dem sich der Inhalt vonsmall_file
befindet (z. B. 0, wenn ersmall_file
zu Beginn übereinstimmtbig_file
). Wennsmall_file
es innen nicht übereinstimmtbig_file
, wird nichts gedruckt. Wenn ein Fehler auftritt, ist der Exit-Status ungleich Null.quelle