Die Aufgabe

Es gibt eine Datei mit vielen Zeilen:

apple ipad
hp touch pad
samsung galaxy tab
motorola xoom

Es soll eine neue Datei entstehen, die nur Zeilen mit einem bestimmten Text enthält, und zwar:

Zeilen, die pad enthalten

apple ipad
hp touch pad

Zeilen, die pad nicht enthalten

samsung galaxy tab
motorola xoom

Wegen dieser vier Zeilen, wird man nicht lange nachdenken und sie einfach händisch bearbeiten, doch das ändert sich, wenn wir an wirklich große Dokumente denken.

Editoren enthalten eine “Suchen-Ersetzen-Funktion”, aber mit dieser Funktion allein ist es nicht getan, weil nicht nur der gefunden Text, sondern auch der Rest der Zeile zu suchen oder zu entfernen ist.

Dafür benötigt man reguläre Ausdrücke (Regular Expressions) und Text-Editoren können damit umgehen. Diese Regex-Funktionalität kann einen Text richtiggehend “sezieren”.

Reguläre Ausdrücke

Vereinfacht gesagt sind diese Ausdrücke eine Kürzelsprache, die bestimmte Zeichen verwendet, um Texte in einem Dokument zu suchen. Wir kennen eine starkt vereinfachte Form solcher Ausdrücke im Zusammenhang mit Dateinamen. Dort gelten die Zeichen * und ? als Platzhalter für viele (*) und ein (?) Zeichen.

Die regulären Ausdrücke enthalten viele solcher Konstrukte (siehe Links). Man muss keineswegs alle lernen, man verbessert sich mit jeder neuen Aufgabe. Texteditoren kann man in einen Regex-Modus umschalten, in dem dann diese Kürzelsprache gilt.

Das “Alles”-Symbol ist kurz folgendes:

. irgendein Zeichen * beliebig oft

Diese Zeichenkombination markiert den ganzen Text. Der Punkt markiert irgend ein Zeichen, der nachfolgende Multiplikator kann sein: * + ?, wobei bedeutet: * 0 oder mehr Zeichen, + 1 oder mehr Zeichen und ? 0 oder 1 Zeichen. Also egal, ob die betrachtete Zeichenfolge leer ist, ein oder mehrere Zeichen enthält, .* erfasst sie alle.

Zum Einstieg die einfache Übung: Um eine Zeile zu finden, die einen bestimmten Text enthält, schreibt man:

^.*text.*$

Dabei ist ^ Zeilenanfang, . irgendein Zeichen, * voriges Zeichen null- oder mehrmal, text der gesuchte Text, $ Zeilenende.

Nun sollen aber alle Zeilen entfernt werden, die einen bestimmten Text nicht enthalten, und das geht so:

 ^(?!.*text.*).+$ 

Der Konstrukt .*text.* bedeutet eine Zeile, die text enthält. (?!) ist eine Negation für das, was folgt; es wird also aus “enthält text” ein “enthält text nicht”. Schließlich ist .+ das, was überbleibt mindestens ein Mal und das wird durch die Suchen-Ersetzen-Funktion durch “” ersetzt.

Bildersuche

Konkret ging es um eine XML-Datei, die Bilddaten enthält und an einer Stelle steht die absolute Pfadangabe zu dem beschriebenen Bild. Und diese Zeile ist erwünscht, alle anderen nicht.

Wo entsteht eine solche XML-Datei? Sie ist das Nebenprodukt einer Exportfunktion in Picasa. Man kann in Picasa ein beliebiges Album in eine Html-Darstellung bringen und dann diesen erzeugten Html-Kode außerhalb von Picasa publizieren.

Diese “Alben” sind nun keine Verzeichnisse, denn das wäre einfach. Ein Album kann ein Querschnitt durch eine gesamte Bildersammlung darstellen. Wenn man zum Beispiel die Gesichtserkennung verwendet und eine bestimmte Person identifiziert, findet Picasa alle weiteren Vorkommen dieser Person und fasst diese Bilder automatisch zu einem Album zusammen. Je nach Bedeutung der Person und Größe der Bildersammlung können das auch sehr viele Bilder sein. Wenn man nun alle diese Bilder, an denen eine bestimmte Person zu sehen ist, ausdrucken oder publizieren will, benötigt man den Pfad zu diesem Bild und diesen findet man in der erwähnten XML-Datei.

Es geht hier nicht um einige Bilder, es geht um Tausende. Und daher ist die Idee, diese Zeilen händisch zu suchen, keine gute. Aber es geht ganz einfach, wenn man das richtige Werkzeug hat. “richtig” ist in diesem Zusammenhang ein guter Editor. Ich habe alle Texteditoren bei Seite geschoben und verwende ausschließlich “Visual Studio Code”. Und dabei kodiere ich gar nicht so viel damit, aber auch als ganz normaler Texteditor ist dieses Programm eine Wucht.

Visual Studio Code im Dark-Mode. braun: gefundener Text, der gelöscht wird.

Man sieht in der “suchen nach”-Zeile den regulären Ausdruck

^(?!.*s\:\\odrive\\onedrive\\fußball.*).+$

Die zweifachen Backslash sind wichtig, weil der Backslash allein ein Escape-Zeichen ist. Das Feld “Replace” bleib leer. braun markiert sind alle Zeilen, die den gesuchten Text nicht enthalten, die Zeile mit dem Pfad ist nicht markiert.

Beachte den rechten Rand, dort ist das gesamte Dokument in einer extrem komprimierten Form dargestellt und man bekommt auf einen Blick einen Überblick über die Treffer.

Wendet man die Suchen-Ersetzen-Funktion an, erhält man viele Leerzeilen, die vorher Text enthalten haben und die gesuchten Zeilen mit den Bildern. Die Leerzeilen löscht man durch wiederholtes Anwenden von “suchen nach \n\n”, “ersetzen durch “\n”.

Zur Illustration hier drei der solcherart isolierten Dateipfade:

...
s:\odrive\onedrive\fußball\rapid\@klub der freunde\@bildarchiv\2017\2017-05-15 kdf gregorits_krammer_peschek\img_20170515_184917.jpg
s:\odrive\onedrive\fußball\rapid\@archiv\rapid i\2015\2015-08-29 rapid-mattersburg\img_1973.jpg 
s:\odrive\onedrive\fußball\rapid\@archiv\rapid i\2015\2015-08-04 ajax-rapid\img-20150803-wa0059.jpg
...

Damit hat man eine Datei mit allen Pfaden zu den gesuchten Bildern und kann diese Datei weiterverarbeiten.

Man sieht an den Pfadnamen, dass der Speicherung eine chronikale Systematik zugrunde liegt, denn man kann aufgrund der Pfadelemente rekonstruieren, um welchen Anlass und um welches Datum es sich gehandelt hat. Wie man daraus ein beschriftetes Bilder-Album erstellt, wird der Inhalt eines weiteren Artikels sein. Es geht letztlich um ein Bilderalbum als Geburtstagsgeschenk.

Links

Franz Fiala

Präsident Clubcomputer / Herausgeber PCNEWS bei ClubComputer.at
Franz ist pensionierter HTL Lehrer (TGM), Präsident von ClubComputer, Herausgeber der Clubzeitung PCNEWS und betreut unser Clubtelefon und Internet Support. Er ist leidenschaftlicher Rapid Wien Fan.

Letzte Artikel von Franz Fiala (Alle anzeigen)