image2data

Der Tech-Blog

...weitermachen, wo OCR aufhört

Reguläre Ausdrücke (RegEx)

Jan 252015

Reguläre Ausdrücke sind ein scharfes Schwert, wenn es darum geht, Nutzdaten aus einem Text zu extrahieren. Zumindest dann, wenn die Struktur der Nutzdaten ungefähr bekannt ist. Über reguläre Ausdrücke sind ganze Bücher geschrieben worden, weswegen eine Einführung in diese den Rahmen dieses Beitrags sprengen würde. Einen kurzen Überblick findet man hier und ein gerne genutzter RegEx-Tester zusammen mit einer schönen Referenz liegt hier.

Ein Beispiel soll die Verwendung eines regulären Ausdrucks in i2dScript veranschaulichen. In dem in ANYTEXT enthaltenen Text soll ein einfaches Datum deutscher Notation (dd.mm.yyyy) gesucht werden. Durch die Verwendung regulärer Ausdrücke ist das ein Einzeiler:

const
  ANYTEXT = 'Lorem ipsum dolor sit amet 07.01.2015 consetetur sadipscing elitr';
  REGEX = '(\d{2}\.\d{2}\.\d{4})';
 
var
  aResults: Ti2dSearchResults;
 
begin
  if i2dGetRegExResults(ANYTEXT, REGEX, aResults) > 0 then
    i2dDebugOut(aResults[0].Match);
end.

So weit, so gut. Nun kann es aber vorkommen, daß ein Beleg in schlechter Qualität vorliegt und eine darauf angewandte Texterkennung entsprechend schlechten Output geliefert hat. So könnte eine "1" als "l" oder eine "0" als "O" erkannt worden sein. Macht nichts, man muß nur den regulären Ausdruck entsprechend gestalten. Hier das Skript von oben, aber mit anderem Text im Datum (die Eins aus dem Monat ist jetzt ein "l" und die Null aus dem Jahr ist jetzt ein "O") und einem RegEx, der gerne vorkommende Erkennungsfehler berücksichtigt:

const
  ANYTEXT = 'Lorem ipsum dolor sit amet 07.0l.2O15 consetetur sadipscing elitr';
  REGEX = '([0-9oOlI]{1,2}\.\s*[0-9oOlI]{1,2}\.\s*[0-9oOlI]{2,4})';
 
var
  aResults: Ti2dSearchResults;
 
begin
  if i2dGetRegExResults(ANYTEXT, REGEX, aResults) > 0 then
    i2dDebugOut(aResults[0].Match);
end.

Der Rückgabewert in den Elementen "Match" kann auch nur Teile des regulären Ausdrucks enthalten. Es wird immer die Entsprechung des gesamten Ausdrucks zurück gegeben oder, wenn Klammern verwendet wurden, die Entsprechung des Ausdrucks innerhalb der äussersten beginnenden Klammer. Ein Beispiel:

const
  ANYTEXT = 'Lorem ipsum dolor sit amet Rechnungsdatum: 07.0l.2O15 consetetur sadipscing elitr';
  REGEX = 'Rechnungsdatum:\s+([0-9oOlI]{1,2}\.\s*[0-9oOlI]{1,2}\.\s*[0-9oOlI]{2,4})';
 
var
  aResults: Ti2dSearchResults;
 
begin
  if i2dGetRegExResults(ANYTEXT, REGEX, aResults) > 0 then
    i2dDebugOut(aResults[0].Match);
end.

Die Funktion hat zwar nach "Rechnungsdatum" gefolgt von dem Ausdruck gesucht, liefert aber in dem Element "Match" nur die Entsprechung des Ausdrucks zurück, in diesem Falle also "07.0l.2O15". Dieses, durch die Zeichen "l" und Null aber immer noch ungültige Datum, kann durch die Funktion "i2dAlmostNumeric2Numeric" in ein gültiges Datum gewandelt werden.

Sollen oder müssen mehrere (Klammer-)Gruppen im regulären Ausdruck verwendet werden, so kann über das Gruppenpräfix "?:" bestimmt werden, ob die Enstprechung einer Gruppe in der Rückgabe unterdrückt werden soll. In dem folgenden Beispiel wird die Rückgabe der Gruppe, die Rechnungsdatum oder Gutschriftsdatum enthält, unterdrückt:

const
 ANYTEXT = 'Lorem ipsum dolor sit amet Rechnungsdatum: 07.0l.2O15 consetetur sadipscing elitr';
 REGEX = '(?:Rechnungsdatum|Gutschriftsdatum):\s+([0-9oOlI]{1,2}\.\s*[0-9oOlI]{1,2}\.\s*[0-9oOlI]{2,4})';
 
var
 aResults: Ti2dSearchResults;
 
begin
 if i2dGetRegExResults(ANYTEXT, REGEX, aResults) > 0 then
 i2dDebugOut(aResults[0].Match);
end.

 

Atom

powered by Nibbleblog