Брайан Керниган представил небольшую статью о Средстве регулярного выражения , которое Роб Пайк написал как демонстрационную программу для книги, над которой работал. Статья очень приятно читается, объясняет немного о коде и регулярных выражениях в целом.
Я поиграл с этим кодом, внеся несколько изменений, чтобы поэкспериментировать с некоторыми расширениями, например, чтобы вернуть, где в строке соответствует шаблон, чтобы подстрока, соответствующая шаблону, могла быть скопирована из исходного текста.
Из статьи:
Я предложил Робу, что нам нужно найти самую маленькую регулярную
пакет выражений, который будет иллюстрировать основные идеи, пока еще
распознавание полезного и нетривиального класса паттернов. В идеале
код поместится на одной странице.
Роб исчез в своем кабинете, и, по крайней мере, насколько я помню это сейчас,
появился снова не более чем через час или два с 30 строками C
код, который впоследствии появился в главе 9 TPOP. Этот код
реализует средство сравнения регулярных выражений, которое обрабатывает следующие конструкции:
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
Это довольно полезный класс; в моем собственном опыте использования регулярного
выражения на повседневной основе, он легко составляет 95 процентов
всех случаев. Во многих ситуациях решение правильной проблемы является
большой шаг на пути к красивой программе. Роб заслуживает большого уважения
для того, чтобы выбирать так мудро, из широкого набора вариантов, очень маленький
но важный, четко определенный и расширяемый набор функций.
Сама реализация Роба - превосходный пример красивого кода:
компактный, элегантный, эффективный и полезный. Это один из лучших примеров
рекурсии, которую я когда-либо видел, и это показывает силу C
указатели. Хотя в то время мы были наиболее заинтересованы в передаче
важную роль хорошей нотации в облегчении программы
использовать и, возможно, проще написать код регулярного выражения
также был отличный способ проиллюстрировать алгоритмы, данные
структуры, тестирование, повышение производительности и другие важные
темы.
Фактический исходный код C из статьи очень, очень приятный.
/* 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;
}