Reguläre Ausdrücke (RegEx)
Jan 252015Regulä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.