Я после нескольких простых примеров и лучших практик использования регулярных выражений в ANSI C. man regex.h
не предоставляет такой большой помощи.
Регулярные выражения в примерах C:?
Ответ 1
Регулярные выражения на самом деле не являются частью ANSI C. Похоже, вы можете говорить о библиотеке регулярных выражений POSIX, которая поставляется с большинством (всего?) * nixes. Здесь пример использования POSIX-регексов в C (на основе this):
#include <regex.h>
regex_t regex;
int reti;
char msgbuf[100];
/* Compile regular expression */
reti = regcomp(®ex, "^a[[:alnum:]]", 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
/* Execute regular expression */
reti = regexec(®ex, "abc", 0, NULL, 0);
if (!reti) {
puts("Match");
}
else if (reti == REG_NOMATCH) {
puts("No match");
}
else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
/* Free memory allocated to the pattern buffer by regcomp() */
regfree(®ex);
В качестве альтернативы вы можете проверить PCRE, библиотеку для совместимых с Perl регулярных выражений в C. Синтаксис Perl довольно это тот же синтаксис, используемый в Java, Python и ряде других языков. Синтаксис POSIX - это синтаксис, используемый grep
, sed
, vi
и т.д.
Ответ 2
Вероятно, это не то, что вы хотите, но инструмент, например re2c, может скомпилировать POSIX (-ish) регулярные выражения для ANSI C. Он написан как замена для lex
, но этот подход позволяет вам жертвовать гибкостью и удобочитаемостью для последнего бит скорости, если вам это действительно нужно.
Ответ 3
man regex.h
сообщает, что для regex.h нет ручного ввода, но man 3 regex
дает вам страницу, объясняющую функции POSIX для сопоставления шаблонов.
Те же функции описаны в Библиотека GNU C: Согласование регулярных выражений, где объясняется, что библиотека GNU C поддерживает как POSIX.2 интерфейс и тот, который библиотека GNU C имела в течение многих лет.
Например, для гипотетической программы, которая печатает, какая из строк, переданных как аргумент, соответствует шаблону, переданному в качестве первого аргумента, вы можете использовать код, похожий на следующий.
#include <errno.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_regerror (int errcode, size_t length, regex_t *compiled);
int
main (int argc, char *argv[])
{
regex_t regex;
int result;
if (argc < 3)
{
// The number of passed arguments is lower than the number of
// expected arguments.
fputs ("Missing command line arguments\n", stderr);
return EXIT_FAILURE;
}
result = regcomp (®ex, argv[1], REG_EXTENDED);
if (result)
{
// Any value different from 0 means it was not possible to
// compile the regular expression, either for memory problems
// or problems with the regular expression syntax.
if (result == REG_ESPACE)
fprintf (stderr, "%s\n", strerror(ENOMEM));
else
fputs ("Syntax error in the regular expression passed as first argument\n", stderr);
return EXIT_FAILURE;
}
for (int i = 2, i < argc, i++)
{
result = regexec (®ex, argv[i], 0, NULL, 0);
if (!result)
{
printf ("'%s' matches the regular expression\n", argv[i]);
}
else if (result == REG_NOMATCH)
{
printf ("'%s' doesn't the regular expression\n", argv[i]);
}
else
{
// The function returned an error; print the string
// describing it.
// Get the size of the buffer required for the error message.
size_t length = regerror (result, ®ex, NULL, 0);
print_regerror (result, length, ®ex);
return EXIT_FAILURE;
}
}
/* Free the memory allocated from regcomp(). */
regfree (®ex);
return EXIT_SUCCESS;
}
void
print_regerror (int errcode, size_t length, regex_t *compiled)
{
char buffer[length];
(void) regerror (errcode, compiled, buffer, length);
fprintf(stderr, "Regex match failed: %s\n", buffer);
}
Последний аргумент regcomp()
должен быть как минимум REG_EXTENDED
, или функции будут использовать основные регулярные выражения, что означает что (например) вам нужно будет использовать a\{3\}
вместо a{3}
, который используется из расширенных регулярных выражений, что, вероятно, вы ожидаете для использования.
POSIX.2 также имеет другую функцию для сопоставления подстановочных знаков: fnmatch()
. Он не позволяет скомпилировать регулярное выражение или получить подстроки, соответствующие подвыражению, но он очень специфичен для проверки, когда имя файла соответствует подстановочному знаку (например, он использует флаг FNM_PATHNAME
).