Регулярное выражение Posix не жадное
есть ли способ использовать не-жадное регулярное выражение В C, как можно использовать в Perl? Я попробовал несколько вещей, но это на самом деле не работает.
в настоящее время я использую это регулярное выражение, которое соответствует IP-адресу и соответствующему HTTP-запросу, но оно жадное, хотя я использую *?:
([0-9]{1,3}(.[0-9]{1,3}){3})(.*?)HTTP/1.1
в этом примере, он всегда соответствует вся строка:
#include <regex.h>
#include <stdio.h>
int main() {
int a, i;
regex_t re;
regmatch_t pm;
char *mpages = "TEST 127.0.0.1 GET /test.php HTTP/1.1" 404 525 "-" "Mozilla/5.0 (Windows NT HTTP/1.1 TEST";
a = regcomp(&re, "([0-9]{1,3}(.[0-9]{1,3}){3})(.*?)HTTP/1.1", REG_EXTENDED);
if(a!=0)
printf(" -> Error: Invalid Regex");
a = regexec(&re, &mpages[0], 1, &pm, REG_EXTENDED);
if(a==0) {
for(i = pm.rm_so; i < pm.rm_eo; i++)
printf("%c", mpages[i]);
printf("n");
}
return 0;
}
$ ./ regtest
127.0.0.1 GET /test.php HTTP / 1.1 " 404 525 " - "" Mozilla / 5.0 (Windows NT HTTP / 1.1
5 ответов
нет, в регулярных выражениях POSIX нет не-жадных кванторов. Но есть библиотека, которая предоставляет Perl-подобные регулярные выражения для C: http://www.pcre.org/
Как я сказал ранее в комментарии, используйте grep -E
для запуска тестов с регексами POSIX, таким образом, время разработки будет улучшено. В любом случае, кажется, ваша проблема заключается в регулярном выражении, а не в отсутствующей функции.
Я не совсем понимаю, что вы хотите захватить из запроса... предположим, вам просто нужен IP-адрес, http-глагол и ресурс, можно получить следующее регулярное выражение.
regcomp(&re, "\b(.?[0-9])+\s+(GET|POST|PUT)\s+([^ ]+)", REG_EXTENDED);
имейте в виду, что несколько предположений были сделаны. Например, это регулярное выражение предполагает, что IP-адрес будет хорошо сформирован, а также запрос с HTTP-глаголом GET, POST, PUT. Редактируйте согласно вашим потребностям.
метод грубой силы получения регулярного выражения для соответствия следующему вхождению слова:
"([^H]|H[^T]|HT[^T]|HTT[^P]|HTTP{^/]|HTTP/[^1]|HTTP/1[^.]|HTTP/1\.[^1])*HTTP/1\.1"
Если вы не можете получить умнее о вашем матче - который вы можете:HTTP-запросов are
Request-Line = Method SP Request-URI SP HTTP-Version CRLF
и ни один из нетерминалов справа матча пробелы. Итак:
"[0-9]{1,3}(\.[0-9]{1,3}){3} [^ ]* [^ ]* HTTP/1\.1"
поскольку вы выделяете пространство только для совпадения всего выражения или возвращаете parens, чтобы получить части.
a = regcomp(&re, "([0-9]{1,3}(\.[0-9]{1,3}){3})(.*?)HTTP/1.1", REG_EXTENDED|REG_ENHANCED);
не имеет этого макроса в старое время
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_8 \
|| __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0
#define REG_ENHANCED 0400 /* Additional (non-POSIX) features */
#endif
в коде pm
массив regmatch_t
, и в вашем случае должно быть не менее 2-4 элементов, в зависимости от того, какие () под-выражения вы хотите захватить.
у вас есть только один элемент. Первый элемент pm[0]
, всегда получает любой текст, соответствующий всему вашему RE. Это то, что ты получишь. Это pm[1]
это получит текст Первого () под-выражения (IP-адрес) и pm[3]
это получит текст, соответствующий вашему (.*?)
срок.
но даже так, как указано выше (Wumbley, W. Q.), библиотека регулярных выражений POSIX может не поддерживать не-жадные кванторы.