Regex, кажется, не прав - не может найти электронную почту
У меня проблема с моей функцией, которая пытается найти адреса электронной почты. Понятия не имею в чем может быть проблема:(
static int contains_mail(const unsigned char *buffer, int length, int detmode)
{
const char *reg_exp = "([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z0-9._%+-]+)";
regex_t regex;
int reti;
regmatch_t matches[2];
int start0, end0, start1, end1;
reti = regcomp(®ex, reg_exp, REG_EXTENDED);
if(reti){ fprintf(stderr, "Could not compile regex\n"); exit(1); }
reti = regexec(®ex, buffer, 2, matches, 0);
start0 = matches[0].rm_so;
end0 = matches[0].rm_eo;
start1 = matches[1].rm_so;
end1 = matches[1].rm_eo;
printf("start0: %d", start0);
printf("end0: %d", end0);
printf("start1: %d", start1);
printf("end1: %d", end1);
if( !reti ){
//printf("1");
return 1;
} else {
//printf("0");
return 0;
}
}
Пример входного файла:
dfo gpdf eriowepower riwope d@b.pl rwepoir weporsdfi dsfdfasdas@sdfaasdas.pl OSIDQOPWIEPOQWIE sdfs@asdsa.pl
WERO IWUEOIRU OWIERU WOIER asdas@asdasd.pl
aposidasop aposdi aspod iaspodi aspoid aspodi sdfsddfsd@asdasd.pl
werowerowe
Похоже, это началось с:
start0: 28end0: 28start1: 1end1: 8
но тогда похоже, что он не знает, что такое конец письма, поэтому я не могу его подсчитать:(
2 ответа
Быстрый вопрос, как вы проходите во входном файле? Как будто я определяю, а затем называю это следующим образом:
char string[] = "dfo gpdf eriowepower riwope d@b.pl rwepoir weporsdfi dsfdfasdas@sdfaasdas.pl OSIDQOPWIEPOQWIE sdfs@asdsa.pl\n\
WERO IWUEOIRU OWIERU WOIER asdas@asdasd.pl\n\
aposidasop aposdi aspod iaspodi aspoid aspodi sdfsddfsd@asdasd.pl\n\
werowerowe\n";
contains_mail(string, 0, 0);
И измените свой contains_mail
функция для многократного вызова regexec
следующим образом:
reti = regexec(®ex, buffer, 2, matches, 0);
while (reti == 0) {
start0 = matches[0].rm_so;
end0 = matches[0].rm_eo;
start1 = matches[1].rm_so;
end1 = matches[1].rm_eo;
printf("start0: %d ", start0);
printf("end0: %d\n", end0);
printf("start1: %d ", start1);
printf("end1: %d\n", end1);
printf("email: %.*s\n", end1 - start1, buffer + start1);
buffer += end1;
reti = regexec(®ex, buffer, 2, matches, REG_NOTBOL);
}
Я получаю все спички:
$ ./email_regex
start0: 28 end0: 34
start1: 28 end1: 34
email: d@b.pl
start0: 19 end0: 42
start1: 19 end1: 42
email: dsfdfasdas@sdfaasdas.pl
start0: 18 end0: 31
start1: 18 end1: 31
email: sdfs@asdsa.pl
start0: 28 end0: 43
start1: 28 end1: 43
email: asdas@asdasd.pl
start0: 47 end0: 66
start1: 47 end1: 66
email: sdfsddfsd@asdasd.pl
Я согласен с другими комментариями, ваше регулярное выражение может быть не лучшим для получения адресов электронной почты. Но что вы на самом деле пытаетесь сделать?
Функция regexec
всегда находит не более одного вхождения вашего регулярного выражения. Первое совпадение (с индексом 0) содержит начальные конечные позиции для всего совпадения, следующие совпадения содержат данные для подвыражений в скобках. (Скобки вокруг целых выражений в вашем примере не имеют смысла, но они приводят к одинаковым позициям для совпадений 0 и 1, возможно, вводя вас в заблуждение, заставляя вас думать, что одни и те же xpressions анализируются много раз.)
Вы можете искать свое выражение в цикле while, где вы перемещаете указатель после успешного совпадения в oder, чтобы найти больше адресов e-nail. Следующая модификация вашего кода печатает все найденные адреса электронной почты и возвращает количество совпадений.
static int contains_mail(const char *buffer, int length)
{
const char *reg_exp =
"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z0-9._%+-]+";
regex_t regex;
regmatch_t match;
int count = 0;
if (regcomp(®ex, reg_exp, REG_EXTENDED) < 0) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
while (regexec(®ex, buffer, 1, &match, 0) == 0) {
int start = match.rm_so;
int end = match.rm_eo;
printf("%.*s\n", end - start, buffer + start);
count++;
buffer = buffer + end;
}
return count;
}