使用regex.h匹配IP地址时正则错误匹配所有字符串的原因
为什么你的C语言正则匹配IP地址会全部显示匹配?
咱们来一步步拆解你遇到的问题——你的正则表达式和调用方式都存在几个关键错误,导致所有测试字符串都被判定为匹配:
1. 未转义的.匹配任意字符
在正则表达式里,.是特殊元字符,用来匹配任意单个字符(包括字母、逗号、点号本身等等)。你想要匹配的是IP地址里的字面点号,必须把它转义成\.;而在C语言字符串中,反斜杠本身需要转义,所以要写成\\.。
2. 正则结构完全不符合IP地址的格式
你的正则[0-9]{1,3}.{3}[0-9]{1,3}的逻辑是:匹配1-3个数字,接着匹配任意3个字符,再匹配1-3个数字。这和IP地址“四段0-255数字用点分隔”的结构完全不沾边,自然会错误匹配很多非IP字符串。
3. 没有锚定字符串的开头和结尾
你没有用^(匹配字符串开头)和$(匹配字符串结尾)来锚定整个正则,这意味着只要字符串中包含符合正则的片段,就会被判定为匹配。比如1111.1.1.1里的111.1.1就符合你的正则,所以会被误判为匹配。
4. 正则语法的模式问题
你调用regcomp时用了No_Regex_Flags(即0),默认使用的是基本正则表达式(BRE),在BRE中,{n,m}这种重复量词需要转义成\{n,m\}才能生效;如果想直接使用{n,m}的写法,需要加上REG_EXTENDED标志来启用扩展正则表达式(ERE)。
修正后的代码
下面是修复后的代码,我们使用正确的IP正则表达式,启用扩展正则,并锚定开头结尾:
#include <stdio.h> #include <regex.h> #define REG_FLAGS REG_EXTENDED // 使用扩展正则表达式 void check_RE(char * r, regex_t RE) { printf ("%s - %s\n", r, !regexec(&RE, r, 0, NULL, 0) ? "Match" : "No Match"); } int main () { regex_t regex; // 匹配0-255的IP段,四段用点分隔,锚定整个字符串 const char* ip_regex = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"; int ret = regcomp(®ex, ip_regex, REG_FLAGS); if(ret) { printf("正则编译失败\n"); return 1; } char RE_list[][32] = { "0.0.0.0", "123.456.789.123", "a.b.c.d", "1.2.34.567", "1111.1.1.1", ".1.1.1", "1,1,1,1" }; for(int i = 0; i < sizeof(RE_list) / sizeof(RE_list[0]); i++) check_RE(RE_list[i], regex); regfree(®ex); // 记得释放正则资源 return 0; }
修正后的输出
运行这段代码后,只有合法的IP地址会被匹配:
0.0.0.0 - Match 123.456.789.123 - No Match a.b.c.d - No Match 1.2.34.567 - No Match 1111.1.1.1 - No Match .1.1.1 - No Match 1,1,1,1 - No Match
补充说明IP正则的逻辑
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)用来匹配0-255的数字段:
25[0-5]:匹配250-2552[0-4][0-9]:匹配200-249[01]?[0-9][0-9]?:匹配0-199(包括一位数、两位数、三位数的0-199)
重复三次这个段加.,最后再匹配一个段,就构成了完整的IP地址格式。
内容的提问来源于stack exchange,提问作者CIsForCookies
相关产品推荐
相关产品推荐

