Wie überprüft man, ob eine Datei Teil einer anderen Datei ist?

8

Ich muss prüfen, ob sich eine Datei in einer anderen Datei befindet. Für ein bestimmtes mehrzeiliges Muster und eine Eingabedatei.

Rückgabewert:

Ich möchte den Status (wie im grep-Befehl) erhalten 0 wenn Übereinstimmungen gefunden wurden, 1 wenn keine Übereinstimmungen gefunden wurden.

Muster:

  • mehrzeilig,
  • Reihenfolge der Zeilen ist wichtig (behandelt als ein einzelner Zeilenblock),
  • enthält Zeichen wie Zahlen, Buchstaben,?, & amp;, *, # usw.,

Erläuterung

Nur die folgenden Beispiele sollten Übereinstimmungen finden:

%Vor%

Folgendes sollte nicht:

%Vor%

Hier ist mein Skript:

%Vor%

Ich kann den Befehl grep für alle Musterzeilen verwenden, aber es schlägt mit diesem Beispiel fehl:

%Vor%

oder auch wenn Sie die Zeilen wechseln: 2 mit 3

%Vor%

gibt 0 zurück, wenn es nicht geht.

Wie kann ich es beheben? Beachten Sie, dass ich lieber native installierte Programme verwenden möchte (wenn dies ohne pcregrp sein kann). Vielleicht sed oder awk kann dieses Problem lösen?

    
user51390233 21.07.2015, 13:45
quelle

3 Antworten

2

Ich habe eine funktionierende Version mit Perl.

Ich dachte, ich hätte mit GNU awk gearbeitet, aber das habe ich nicht getan. RS = leerer String teilt sich auf Leerzeilen auf. Siehe den Bearbeitungsverlauf für die defekte awk-Version.

Wie kann ich nach einer Multilinie suchen? Muster in einer Datei? zeigt, wie man pcregrep verwendet, aber ich sehe keine Möglichkeit, es zum Laufen zu bringen, wenn das zu suchende Muster Regex-Sonderzeichen enthalten kann. -F Fixed-String-Modus funktioniert nicht sinnvoll mit Multi-Line-Modus: Es behandelt immer noch das Muster als eine Reihe von Zeilen separat zugeordnet werden. (Nicht als eine mehrzeilige feste Zeichenfolge, die abgeglichen werden muss.) Ich sehe, dass Sie pcregrep bereits bei Ihrem Versuch verwendet haben.

Übrigens, ich glaube, Sie haben einen Fehler in Ihrem Code im Nicht-Sudo-Fall:

%Vor%

Wie auch immer, Versuche, linienbasierte Werkzeuge zu verwenden, sind gescheitert, daher ist es an der Zeit, eine ernstere Programmiersprache zu entwickeln, die uns die Newline-Konvention nicht erzwingt. Lies einfach beide Dateien in Variablen und verwende eine Nicht-Regex-Suche:

%Vor%

Siehe Was ist der beste Weg, eine Datei in Perl zu schlürfen? , um die Abhängigkeit von File::Slurp zu vermeiden (die nicht Teil der Standard-Perl-Distribution oder eines Standard-Ubuntu 15.04-Systems ist). Ich ging für File :: Slurp teilweise für die Lesbarkeit des Programms, für Nicht-Perl-Geeks, im Vergleich zu:

%Vor%

Ich habe daran gearbeitet, das Lesen der gesamten Datei in den Speicher zu vermeiden, mit einer Idee von Ссылка . Ich denke, dass nicht übereinstimmende Fälle in der Regel immer noch die ganze Datei auf einmal lesen würden. Außerdem war die Logik ziemlich komplex für die Behandlung einer Übereinstimmung am Anfang der Datei, und ich wollte nicht lange testen, um sicherzustellen, dass sie für alle Fälle korrekt war. Hier ist, was ich hatte, bevor ich aufgab:

%Vor%

Eine weitere Idee war, Muster und Dateien zu filtern, die durch tr '\n' '\r' oder etwas gesucht werden, so dass sie alle einzeilig sind. ( \r ist wahrscheinlich eine sichere Wahl, die nicht mit etwas kollidieren würde, das bereits in einer Datei oder einem Muster vorhanden ist.)

    
Peter Cordes 22.07.2015, 05:50
quelle
4

Ich würde einfach diff für diese Aufgabe verwenden:

%Vor%

Erklärung

  • diff file1 file2 meldet, wenn sich zwei Dateien unterscheiden oder nicht.

  • Wenn Sie grep -f file pattern sagen, sehen Sie, welcher Inhalt von pattern in file ist.

Sie überprüfen also, welche Zeilen von pattern in file sind und vergleichen diese dann mit pattern selbst. Wenn sie übereinstimmen, bedeutet dies, dass pattern eine Untermenge von file ist!

Tests

seq 10 ist ein Teil von seq 20 ! Lass es uns überprüfen:

%Vor%

seq 10 ist nicht genau in seq 2 20 (1 ist nicht in der zweiten):

%Vor%     
fedorqui 21.07.2015 14:11
quelle
2

Ich habe das Problem noch einmal durchgegangen und ich denke, awk kann das besser handhaben:

%Vor%

Die Idee ist: - Lies alle Dateien file im Speicher in einem Array a[line_number] = line . - Zählen Sie die Elemente im Array. - Durchlaufe die Datei pattern und überprüfe, ob die aktuelle Zeile immer in file zwischen dem Cursor und dem Ende der Datei file auftritt. Wenn es übereinstimmt, bewegen Sie den Cursor an die Stelle, an der es gefunden wurde. Ist dies nicht der Fall, setzen Sie den Status auf 1 - das heißt, es gibt eine Zeile in pattern , die nach der vorherigen Übereinstimmung nicht in file aufgetreten ist. - Drucken Sie den Status, der 0 ist, es sei denn, es wurde vorher auf 1 gesetzt.

Test

Sie stimmen überein:

%Vor%

Sie nicht:

%Vor%

Mit seq :

%Vor%     
fedorqui 22.07.2015 11:08
quelle

Tags und Links