Anfänger-Tutorial

Was ist pica?

pica ist ein Set von Kommandozeilen-Tools zur Arbeit mit PICA+-Bibliothekskatalog-Daten. Große Datenabzüge bis hin zu Gesamtabzügen können schnell gefiltert werden und es können die Daten einzelner Felder und Unterfelder in CSV-Dateien exportiert werden, Häufigkeitsverteilungen des Inhalts einzelner Unterfelder erfasst werden und vieles mehr.

Wie funktioniert pica?

Das Tool kann mit extrem großen Dateien umgehen, weil es diese sequentiell ausliest und prozessiert. Die Dateien werden nicht geöffnet und in den Arbeitsspeicher geladen, sondern ›häppchenweise‹ ausgewertet. Es ist deswegen kein Rechner mit besonders viel Arbeitsspeicher notwendig. Es empfiehlt sich aber, die Ausgangsdaten auf möglichst schnellen lokalen Laufwerken abzulegen. Netzlaufwerke sind weniger geeignet und verlangsamen das Tool unnötig.

pica läuft unter Windows, Linux und Mac OS.

Installation

Es ist möglich, die Quelldateien herunterzuladen und direkt auf dem eigenen Rechner von Rust zu einem lauffähigen Programm kompilieren zu lassen.

Für die gängigen Windows-, Apple- oder Linux-Systeme, stehen aber fertige Programmpakete unter https://github.com/deutsche-nationalbibliothek/pica-rs/releases zur Verfügung. Unter Installation sind für die Betriebssysteme Windows, Linux und macOS die Schritte zur Einrichtung des Tools beschrieben.

Kommandozeile

pica ist auch deswegen sehr schnell, weil es kein grafisches Interface hat. Man sollte deshalb einige Basics der Kommandozeilen (auch Terminal oder Shell genannt) des jeweiligen Betriebssystems kennen. Alle Befehle werden hier in der Fassung für gängige Linux- und macOS-Terminals gezeigt, abweichende Befehle der Windows Power Shell werden meistens in Klammern erwähnt.

Pipes

Um das Tool optimal nutzen zu können, sollten Sie verstehen, was Pipes sind. Im Terminal wird die Ausgabe ausgeführter Programme oder Befehle üblicherweise in die sogenannte Standardausgabe (stdout) geschrieben. Normalerweise ist das die Bildschirmausgabe des Terminals selbst. Wenn sie z. B. den Inhalt des aktuellen Ordners mit ls (Windows: dir) auslesen, wird eine Liste aller Dateien und Ordner direkt im Terminal ausgegeben.

Sie könnten diese Ausgabe aber auch umleiten: z.B. in eine Datei oder auf einen angeschlossenen Drucker.

Piping nennt man ein Verfahren, bei dem die Ausgabe eines Befehls direkt als Eingabe für einen weiteren Befehl verwendet wird. Wie Rohre (pipes) werden die Befehle aneinandergesteckt und die Daten fließen von einem Programm zum nächsten.

Dazu werden die Befehle mit einem senkrechten Strich verbunden: | Unter Linux und Windows ist dieser Strich normalerweise über die Tastenkombination AltGr-< zu erreichen, unter MacOS über Alt-7.

Man könnte also z. B. die Ausgabe von ls bzw. dir an einen Befehl weiterleiten, der die Anzahl der ausgegeben Zeilen zählt. Dieser Befehl heißt wc -l (von word count -lines). Das korrekte Piping geht so:

$ ls | wc -l

Die Ausgabe von Word Count lässt sich wieder weiterleiten, z.B. in eine Datei:

$ ls | wc -l > ordnerinhalt.txt

Der >-Operator leitet den Inhalt in eine Datei weiter und ist eine Art Sonderfall des Pipings, der nur für das Schreiben in Dateien gilt.

Man könnte die Ausgabe mit einer weiteren Pipe auch an noch einen weiteren Befehl übergeben.

Mit Pipes lassen sich die einzelnen pica-rs-Tools (select, filter, frequency usw.) miteinander verknüpfen. Die Ausgabe des einen Tools kann entweder zum nächsten Tool, in eine Datei oder einfach auf den Bildschirm geleitet werden. Alle Tools schreiben immer in die Standardausgabe. Will man die Ausgabe anders erhalten, muss man das dem Befehl mitteilen.

Los geht’s

Navigieren Sie im Terminal zu dem Ordner, in dem Ihre Daten liegen. Wir gehen davon aus, dass Sie im Hauptverzeichnis Ihres aktuellen Benutzers (unter Linux und Mac OS über das Kürzel ~ zu erreichen) im Verzeichnis pica-test arbeiten. Das Testdatenpaket heißt testdaten.dat.

$ cd ~/pica-test

Überprüfen Sie, ob das Testdatenpaket vorhanden ist.

$ ls # (unter Windows: dir)
total 1872
drwxr-xr-x   3 testuser  staff    96B  9 Nov 14:24 .
drwxr-xr-x+ 76 testuser  staff   2,4K  9 Nov 14:25 ..
-rw-r--r--@  1 testuser  staff   935K 14 Sep 18:30 testdaten.dat

print

Wir beginnen mit print. Dieses Kommado formatiert die unleserlichen PICA+-Daten zu gut lesbaren Datensätzen. Mit dem Befehl lassen sich die teilweise unübersichtlichen Daten überblicken. Wir wollen nur einen Datensatz aus den Testdaten auf dem Bildschirm ausgeben.

$ pica print -l 1 testdaten.dat

Die Option -l steht für Limit und begrenzt die Ausgabe auf eine bestimmte Anzahl von Datensätzen am Beginn der Datei. Die folgende Ziffer gibt die Anzahl der auszugebenden Datensätze an.

Wir können die Ausgabe auch mit der Option -o in eine Datei schreiben:

$ pica print -l 1 testdaten.dat -o testdatensatz.txt

Wenn Sie nur einen Dateinamen angeben, wird die Datei im aktuellen Verzeichnis abgelegt. Wollen Sie in ein anderes Verzeichnis schreiben, müssen Sie den kompletten Pfad dorthin angeben.

Im Folgenden gehen wir davon aus, dass Sie grundlegend mit der Struktur von Pica-Daten vertraut sind, also z. B. Feldern, Unterfeldern, Satzarten und Codes.

filter

Mit filter können Teilmengen aus einem Daten-Dump nach einem bestimmten Selektionskriterium gebildet werden. filter gibt grundsätzlich den ganzen Datensatz aus, wenn die angegebenen Filterkriterien erfüllt sind.

Wir wissen, dass in unseren Testdaten jeweils 100 Datensätze der unterschiedlichen Satzarten enthalten sind. Wir wollen alle Oa-Sätze herausfiltern und den ersten davon mit print ausgeben.

$ pica filter -s "002@.0 == 'Oa'" testdaten.dat | pica print -l 1

Das Ergebnis könnte man auch wieder in eine Datei schreiben:

$ pica filter -s "002@.0 == 'Oa'" testdaten.dat -o oa-test.dat
Vorsicht

Dateien werden ohne Rückfrage überschrieben und werden nicht im Papierkorb gesichert. Gewöhnen Sie sich am besten an, in ein eigenes Ausgabeverzeichnis zu schreiben oder fügen Sie das aktuelle Datum an den Ausgabedateinamen an, damit Sie nicht aus Versehen eine ältere Datei überschreiben.

Filter-Ausdrücke

Der Filterausdruck ist das mächtigste Werkzeug von pica. Mehrere Ausdrücke können zu komplexen Suchfiltern kombiniert werden.

Jeder Filterausdruck besteht immer aus einem Feld wie 002@, einem Unterfeldfilter wie .0, einem Operator, der angibt, wie der Inhalt des Feldes gefiltert werden soll, wie z. B. == und einem Wert, mit dem das Feld verglichen werden soll.

Felder

Felder können in der einfachsten Form direkt benannt werden: 002@ oder auch nummerierte Okkurrenzen haben wie /01. Okkurrenzen lassen sich nach ihrem Wert filtern oder alle Okkurrenzen können mit /* durchsucht werden. Bereiche von Okkurrenzen können ebenfalls eingegrenzt werden: 047A/01-03

Unterfelder

Unterfelder werden mit einem Punkt und ohne Dollarzeichen angehängt: 002@.0 meint Unterfeld $0 von Feld 002@.

Um z. B. Unterfeld 9 aller Okkurrenzen von Feld 041A zu filtern, müsste der Feldausdruck lauten: 041A/*.9.

Operatoren

Werte können mittels der folgenden Operatoren verglichen werden:

Gleichheit ==
Der ==-Operator prüft, ob es ein Unterfeld gibt, dass einem Wert entspricht. pica filter "021A.a == 'abc'" liest sich wie folgt: Es existiert ein Feld 021A mit einem Unterfeld a das gleich abc ist. Es könnten noch weitere Unterfelder a existieren, die nicht abc sind.
Ungleichheit !=
Das Gegenstück zu ==. Prüft, ob ein Unterfeld existiert, das nicht einem Wert entspricht.
Beginnt mit Präfix =^ (!^)
Der Ausdruck wird dann wahr, wenn der Wert des Unterfelds mit dem angegebenen Präfix beginnt (=^) bzw. nicht beginnt (!^).
Endet mit Suffix =$ (!$)
Der Ausdruck wird dann wahr, wenn der Wert des Unterfelds mit dem angegebenen Suffix endet (=$) bzw. nicht beginnt (!$).
Regulären Ausdruck =~ (!~)
Prüft ob ein Feld einem regulären Ausdruck entspricht. Die Auswertung dieses Operators benötigt die meiste Rechenkapazität. Er sollte deshalb nur dann verwendet werden, wenn er wirklich absolut notwendig ist. Es ist z. B. schneller, nach einer Kombination von =^ und =$ zu suchen als nach einem regulären Ausdruck.
Enthalten in in (not in)
Der Ausdruck wird dann wahr, wenn der Wert des Unterfelds in der angegebenen Liste enthalten ist (in) bzw. nicht enthalten ist (not in).
Teilstring =?
Der Ausdruck wird dann wahr, wenn der angegebene Wert ein Teilstring des Unterfelds ist (=?).
Existenz ?
Der Ausdruck wird dann wahr, wenn das gesuchte Feld/Unterfeld existiert.
Ähnlichkeit =*
Der Ausdruck wird dann wahr, wenn der angegebene Wert ähnlich dem des Unterfelds ist. Die gewünschte Unschärfe kann über die Option --strsim-threshold parametrisiert werden.

Die Operatoren können in runden Klammern gruppiert und mit den booleschen Operatoren UND &&, ODER || sowie XOR (^) verbunden werden.

Mehrere Felder adressieren

Es kommt öfters vor, dass sich ein Wert vom gleichen Typ in unterschiedlichen Feldern befindet. Z. B. befindet sich im Feld 028A.9 die “Person, Familie - 1. geistiger Schöpfer” und im Feld 028C.9 “Person, Familie - weitere geistige Schöpfer”. Um Datensätze zu filtern, die entweder einen 1. geistigen Schöpfer oder einen weiteren geistigen Schöpfer haben, könnte man schreiben:

$ pica filter "028A.9? || 028C.9?" testdaten.dat

Der Ausdruck lässt sich vereinfachen zu:

$ pica filter "028[AC].9?" testdaten.dat

An jeder Position in einem Feld kann eine Liste der gültigen Werte angegeben werden. Es wird dann jede mögliche Kombination ausprobiert, um einen Match zu finden. Bsp. 0[12][34]A führt zu der Liste 013A, 014A, 023A und 024A.

Mehrere Unterfelder adressieren

So ähnlich können auch mehrere Unterfelder adressiert werden. Beispiel: Im Feld 045E befindet sich die Sachgruppe der Deutschen Nationabibliografie. Im Unterfeld $e die Hauptsachgruppe (HSG) und im Feld $f die Nebensachgruppen (NSG). Ist man an allen Datensätzen interessiert, die zur HSG 100 oder zur NSG 100 gehören, könnte man folgenden Filter schreiben:

$ pica filter "045E.e == '100' || 045E.f == '100'" testdaten.dat

Der Ausdruck lässt sich verkürzen zu:

$ pica filter "045E.[ef] == '100'" testdaten.dat

Beide Verfahren sind kombinierbar: 0[12]3[AB].[xyz] ist ein gültiger Ausdruck.

Select

Mit select können die Werte einzelner Unterfelder in eine CSV-Datei exportiert werden. Dabei können mehrere Unterfelder kombiniert werden. Man kann aus riesigen Datenbeständen exakt die Daten extrahieren, die man für weitere Datenanalysen benötigt.

Der Selektionsausdruck enthält eine durch Kommas getrennte Liste von Unterfeldern, die ausgelesen werden sollen, z. B.:

$ pica select "002@.0, 003@.0" testdaten.dat -o test-select.csv

Das Ergebnis ist eine CSV-Datei mit zwei Spalten, in diesem Beispiel einer Spalte für die Satzart und einer Spalte für die IDN.

Wenn Felder mehrere Unterfelder haben, können diese in einer Liste in geschweiften Klammern an die Feldbezeichnung angehängt werden.

$ pica select "002@.0, 003@.0, 021A{a,h}" testdaten.dat -o test-select.csv

In die Selektionsausdrücke können auch Filterausdrücke eingebaut werden. Dazu muss die erste Position der Liste in den geschweiften Klammern ergänzt werden.

$ pica select "003@.0, 028A{ (9,d,a) | 4 == 'aut' }" testdaten.dat -o test-select.csv

In diesem Beispiel werden die Angaben zur Person aus Feld 028A nur übernommen, wenn Unterfeld 4 den Wert aut enthält, die Person also Autor*in ist und nicht etwa Herausgeber*in.

Für diese Filterausdrücke gelten dieselben Regeln wie für Filterausdrücke im filter-Tool, die oben beschrieben wurden.

Wenn Felder wiederholbar sind (z. B. bei Schlagworten), wird pro Wiederholung eine neue Zeile in die CSV ausgegeben. Die ausgegebene CSV-Datei kann also mehr Zeilen enthalten, als Datensätze in den Ausgangsdaten waren. Es empfiehlt sich deshalb einen eindeutigen Identifikator mitzuselektieren, damit die wiederholten Felddaten von neuen Datensätzen unterschieden werden können.

Es können auch Spaltennamen für die CSV-Ausgabe angegeben werden mit der Option -H. Wichtig: die Anzahl Spaltennamen muss der Anzahl der selektierten Unterfelder entsprechen.

$ pica select -H "idn, autor-idn, autor-vorname, autor-nachname" \
    "003@.0, 028A{ 9,d,a | 4 == 'aut' }" testdaten.dat -o test-select.csv
Hinweis

Die doppelte Filtermöglichkeit einmal mit dem filter-Kommando und einmal im select-Kommando verwirrt auf den ersten Blick etwas. filter prüft eine oder mehrere Felder oder Unterfelder auf Bedingungen und gibt den gesamten Datensatz aus, wenn die Bedingung wahr ist. select prüft ebenfalls auf Bedingungen und selektiert dann die benötigten Teildaten. Man könnte auch sagen: filter arbeitet auf Datensatzebene und select auf Feldebene.

Arbeit mit großen Datenabzügen

pica parst immer den kompletten Datenbestand, auch wenn man nur wenige Ergebnisse erwartet. Deshalb ist es manchmal sinnvoll, die Ausgangsdatei in kleinere Dateien zu teilen, die dann viel schneller verarbeitet werden können.

In unseren Testdaten haben wir Titeldaten und Normdaten zusammen. Es könnte z.B. sinnvoll sein, die Normdaten zu extrahieren, wenn man keine Titeldaten braucht oder nur eine bestimmte Satzart zu extrahieren, wenn man nur innerhalb dieser Satzart suchen will.