[英]Posix regular expression non-greedy
有沒有辦法在 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
不,POSIX 正則表達式中沒有非貪婪量詞。 但是有一個庫為 C 提供了類似 perl 的正則表達式: 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請求是
Request-Line = Method SP Request-URI SP HTTP-Version CRLF
並且右邊的非終結符都不匹配嵌入的空格。 所以:
"[0-9]{1,3}(\\.[0-9]{1,3}){3} [^ ]* [^ ]* HTTP/1\\.1"
因為您只是為整個表達式匹配分配空間,或者將括號放回原處以獲取碎片。
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,WQ)POSIX 正則表達式庫可能不支持非貪婪量詞。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.