Регулярное выражение 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 может не поддерживать не-жадные кванторы.