我尝试使用 regex.h
但没有成功。我正在尝试匹配一个 IP 地址
#include <stdio.h>
#include <regex.h>
#define No_Regex_Flags 0
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;
int ret = regcomp(®ex, "[0-9]{1,3}.{3}[0-9]{1,3}", No_Regex_Flags);
if(ret)
printf("err1\n");
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);
return 0;
}
但是,我得到的输出总是匹配的:
0.0.0.0 - Match
123.456.789.123 - Match
a.b.c.d - Match
1.2.34.567 - Match
1111.1.1.1 - Match
.1.1.1 - Match
1,1,1,1 - Match
这是为什么?
最佳答案
使用
int ret = regcomp(®ex, "^([0-9]{1,3}\\.){3}[0-9]{1,3}$", REG_EXTENDED);
或者,更高效的方式:
int ret = regcomp(®ex, "^[0-9]{1,3}(\\.[0-9]{1,3}){3}$", REG_EXTENDED);
参见 this regex demo,它也匹配错误的 IP 地址,如 1.2.34.567
和 123.456.789.123
。所以,我建议一个更精确的(来源:regular-expresions.info):
"^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}$"
参见 this regex demo。
参见 C demo 。输出是
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
兴趣点
- 点匹配任何字符,所以你必须在模式中用
\\
转义它 - 如果您必须重复一系列模式,则需要将它们分组并量化该组:
[0-9]{1,3}\\.{3}
=>([0-9]{1,3}\\.){3}
- 要匹配整个字符串,您需要 anchor 、
^
和围绕模式的$
- 要使
$
anchor 工作,您需要将REG_EXTENDED
标志传递给regcomp
。如果您计划使用{3}
而不必转义{
和}
,那么它也是必需的。否则,您将不得不遵循 BRE POSIX 规范并编写一个限制量词,例如\{3\}
- 由于
[0-9]{1,3}
匹配任何 3 位数字,原始模式并不是真正验证 IP 地址,因此您需要将八位字节值限制为0
..255
。因此,应该使用交替组(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])
来匹配一个八位字节。
这是八位位组模式的解释:
-
25[0-5]
-250
到255
-
|
- 或 -
2[0-4][0-9]
-200
到249
-
|
- 或 -
1[0-9][0-9]
-100
到199
-
|
- 或 -
[1-9]?[0-9]
-0
到99
。
关于c - 正则表达式匹配错误的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50598736/