Brian Kernighan hat einen kurzen Artikel über Ein Abgleich mit regulären Ausdrücken que Rob Pike als Demonstrationsprogramm für ein Buch geschrieben, an dem sie arbeiteten. Der Artikel ist sehr lesenswert und erklärt ein wenig über den Code und reguläre Ausdrücke im Allgemeinen.
Ich habe mit diesem Code gespielt und einige Änderungen vorgenommen, um mit einigen Erweiterungen zu experimentieren, wie z. B. die Rückgabe der Stelle in der Zeichenkette, an der das Muster übereinstimmt, so dass die Teilzeichenkette, die dem Muster entspricht, aus dem Originaltext kopiert werden kann.
Aus dem Artikel:
Ich habe Rob vorgeschlagen, dass wir die Ausdruckspaket zu finden, das die grundlegenden Ideen veranschaulicht und gleichzeitig eine nützliche und nicht triviale Klasse von Mustern erkennt. Idealerweise sollte der Code auf eine einzige Seite passen.
Rob verschwand in seinem Büro, ein erschien er innerhalb von ein oder zwei Stunden wieder mit den 30 Zeilen C Code, der anschließend in Kapitel 9 von TPOP erschien. [ ] implementiert einen Matcher für reguläre Ausdrücke, der diese Konstrukte verarbeitet:
c matches any literal character c
. matches any single character
^ matches the beginning of the input string
$ matches the end of the input string
* matches zero or more occurrences of the previous character
Dies ist eine recht nützliche Klasse; nach meiner eigenen Erfahrung bei der Verwendung regulärer Ausdrücke im täglichen Gebrauch, macht sie leicht 95 Prozent aller aller Fälle. In vielen Situationen ist das Lösen des richtigen Problems ein ein großer Schritt auf dem Weg zu einem schönen Programm. Rob gebührt große Anerkennung dafür, dass er aus einer großen Anzahl von Optionen eine sehr kleine, aber wichtige aber dennoch wichtigen, gut definierten und erweiterbaren Satz von Funktionen.
Die Umsetzung von Rob selbst ist eine großartige kompakt, elegant, effizient und nützlich. Es ist eines der besten Beispiele der Rekursion, die ich je gesehen habe, und es zeigt die Leistungsfähigkeit von C Zeigern. Obwohl wir damals vor allem daran interessiert waren, zu vermitteln die wichtige Rolle einer guten Notation für die Benutzerfreundlichkeit eines Programms und vielleicht auch einfacher zu schreiben ist, ist der Code für reguläre Ausdrücke auch eine hervorragende Möglichkeit, Algorithmen, Datenstrukturen Strukturen, Testen, Leistungssteigerung und andere wichtige Themen.
Der eigentliche C-Quellcode aus dem Artikel ist sehr, sehr schön.
/* match: search for regexp anywhere in text */
int match(char *regexp, char *text)
{
if (regexp[0] == '^')
return matchhere(regexp+1, text);
do { /* must look even if string is empty */
if (matchhere(regexp, text))
return 1;
} while (*text++ != '\0');
return 0;
}
/* matchhere: search for regexp at beginning of text */
int matchhere(char *regexp, char *text)
{
if (regexp[0] == '\0')
return 1;
if (regexp[1] == '*')
return matchstar(regexp[0], regexp+2, text);
if (regexp[0] == '$' && regexp[1] == '\0')
return *text == '\0';
if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
return matchhere(regexp+1, text+1);
return 0;
}
/* matchstar: search for c*regexp at beginning of text */
int matchstar(int c, char *regexp, char *text)
{
do { /* a * matches zero or more instances */
if (matchhere(regexp, text))
return 1;
} while (*text != '\0' && (*text++ == c || c == '.'));
return 0;
}